package applogic

import (
	"fmt"
	"strings"
	"time"

	"aijianzhan/platform/internal/authx"
	"aijianzhan/platform/internal/invitestore"
	"aijianzhan/platform/internal/types"
	"aijianzhan/platform/internal/userstore"
)

type PlatformLogic struct {
	*AuthLogic
}

type CreateTenantResult struct {
	Tenant       *userstore.TenantInfo `json:"tenant"`
	AdminAccount *AdminAccountOut      `json:"admin_account,omitempty"`
	AdminInvite  *invitestore.Invite   `json:"admin_invite,omitempty"`
}

// AdminAccountOut 新建公司时下发的公司管理员凭据（密码仅此一次明文返回）。
type AdminAccountOut struct {
	UserID                int64  `json:"user_id"`
	Username              string `json:"username"`
	Password              string `json:"password,omitempty"`
	Phone                 string `json:"phone,omitempty"`
	UsernameLoginDisabled bool   `json:"username_login_disabled,omitempty"`
	DisplayName           string `json:"display_name"`
	Role                  string `json:"role"`
}

type AdminInfo struct {
	UserID                int64  `json:"user_id"`
	Username              string `json:"username"`
	Phone                 string `json:"phone"`
	UsernameLoginDisabled bool   `json:"username_login_disabled"`
	DisplayName           string `json:"display_name"`
	Role                  string `json:"role"`
	Status                string `json:"status"`
}

func NewPlatformLogic(l *AuthLogic) *PlatformLogic {
	return &PlatformLogic{AuthLogic: l}
}

func (l *PlatformLogic) requireSuper() (*userstore.User, error) {
	if !authx.IsPlatformAdmin(authx.Role(l.ctx)) {
		return nil, fmt.Errorf("需要超级管理员")
	}
	u, err := l.svcCtx.Users.GetByID(l.ctx, authx.UserID(l.ctx))
	if err != nil {
		return nil, err
	}
	if !u.IsPlatformAdmin() {
		return nil, fmt.Errorf("需要超级管理员")
	}
	return u, nil
}

func (l *PlatformLogic) ListTenants() ([]userstore.TenantInfo, error) {
	if _, err := l.requireSuper(); err != nil {
		return nil, err
	}
	return l.svcCtx.Users.ListTenants(l.ctx)
}

func (l *PlatformLogic) CreateTenant(name, slug string, withAdminInvite bool, adminPhone string) (*CreateTenantResult, error) {
	super, err := l.requireSuper()
	if err != nil {
		return nil, err
	}
	phone := strings.TrimSpace(adminPhone)
	if l.phoneLoginOnly() && phone == "" {
		return nil, fmt.Errorf("本部署仅手机号登录，请填写管理员手机号")
	}
	t, err := l.svcCtx.Users.CreateTenant(l.ctx, strings.TrimSpace(name), strings.TrimSpace(slug))
	if err != nil {
		return nil, err
	}
	if l.svcCtx.Roles != nil {
		_ = l.svcCtx.Roles.EnsureDefaults(l.ctx, t.TenantID)
	}
	if l.svcCtx.TenantPerm != nil {
		_ = l.svcCtx.TenantPerm.EnsureDefault(l.ctx, t.TenantID)
	}
	out := &CreateTenantResult{Tenant: t}

	acc, aerr := l.createCompanyAdmin(t.TenantID, strings.TrimSpace(name), phone)
	if aerr != nil {
		return nil, fmt.Errorf("创建公司成功，但管理员账号生成失败: %v", aerr)
	}
	out.AdminAccount = acc

	if withAdminInvite && l.svcCtx.Invites != nil {
		inv, ierr := l.svcCtx.Invites.Create(l.ctx, t.TenantID, super.UserID, invitestore.CreateInput{
			Role:      authx.Role管理员,
			MaxUses:   1,
			ExpiresIn: 7 * 24 * time.Hour,
		})
		if ierr == nil {
			out.AdminInvite = inv
		}
	}
	return out, nil
}

// createCompanyAdmin 生成随机唯一管理员；phone 非空时绑定手机。
func (l *PlatformLogic) createCompanyAdmin(tenantID int64, companyName, phone string) (*AdminAccountOut, error) {
	uname, err := userstore.AllocUniqueUsername(l.ctx, l.svcCtx.Users.UsernameExists)
	if err != nil {
		return nil, err
	}
	display := strings.TrimSpace(companyName)
	if display == "" {
		display = "公司"
	}
	display += "管理员"
	u, plain, err := l.svcCtx.Users.CreateMember(l.ctx, tenantID, uname, "", display, authx.Role管理员, 0)
	if err != nil {
		if strings.Contains(err.Error(), "already exists") {
			uname2, e2 := userstore.AllocUniqueUsername(l.ctx, l.svcCtx.Users.UsernameExists)
			if e2 != nil {
				return nil, e2
			}
			u, plain, err = l.svcCtx.Users.CreateMember(l.ctx, tenantID, uname2, "", display, authx.Role管理员, 0)
		}
		if err != nil {
			return nil, err
		}
	}
	out := &AdminAccountOut{
		UserID: u.UserID, Username: u.Username, Password: plain,
		DisplayName: u.DisplayName, Role: u.Role,
	}
	phone = strings.TrimSpace(phone)
	if phone == "" {
		return out, nil
	}
	ns, nerr := userstore.NormalizePhone(phone)
	if nerr != nil {
		return nil, nerr
	}
	nu, berr := l.svcCtx.Users.BindPhone(l.ctx, u.UserID, ns)
	if berr != nil {
		return nil, fmt.Errorf("账号已创建但绑定手机失败: %v", berr)
	}
	out.Phone = nu.Phone
	return out, nil
}

// IssueAdminAccount 为已有公司再发一个管理员账号；有期限控制时手机号可选。
func (l *PlatformLogic) IssueAdminAccount(tenantID int64, adminPhone string) (*AdminAccountOut, error) {
	if _, err := l.requireSuper(); err != nil {
		return nil, err
	}
	if l.phoneLoginOnly() && strings.TrimSpace(adminPhone) == "" {
		return nil, fmt.Errorf("本部署仅手机号登录，请填写管理员手机号")
	}
	t, err := l.svcCtx.Users.GetTenant(l.ctx, tenantID)
	if err != nil {
		return nil, err
	}
	return l.createCompanyAdmin(t.TenantID, t.Name, adminPhone)
}

// ListCompanyAdmins 列出该公司人类管理员账号（用户名唯一不可改）。
func (l *PlatformLogic) ListCompanyAdmins(tenantID int64) ([]AdminInfo, error) {
	if _, err := l.requireSuper(); err != nil {
		return nil, err
	}
	if _, err := l.svcCtx.Users.GetTenant(l.ctx, tenantID); err != nil {
		return nil, err
	}
	members, err := l.svcCtx.Users.ListMembers(l.ctx, tenantID)
	if err != nil {
		return nil, err
	}
	out := make([]AdminInfo, 0)
	for _, u := range members {
		if !authx.IsCompanyAdmin(u.Role) {
			continue
		}
		out = append(out, AdminInfo{
			UserID: u.UserID, Username: u.Username, Phone: u.Phone,
			UsernameLoginDisabled: u.UsernameLoginDisabled,
			DisplayName: u.DisplayName, Role: u.Role, Status: u.Status,
		})
	}
	return out, nil
}

// UpdateCompanyAdmin 平台超管重置该公司管理员密码 / 绑定手机 / 禁用用户名登录（用户名不变）。
func (l *PlatformLogic) UpdateCompanyAdmin(tenantID, userID int64, resetPassword bool, password string, phone *string, disableUsernameLogin *bool) (*AdminAccountOut, error) {
	if _, err := l.requireSuper(); err != nil {
		return nil, err
	}
	if _, err := l.svcCtx.Users.GetTenant(l.ctx, tenantID); err != nil {
		return nil, err
	}
	u, err := l.svcCtx.Users.GetByID(l.ctx, userID)
	if err != nil {
		return nil, err
	}
	if u.TenantID != tenantID {
		return nil, fmt.Errorf("成员不属于该公司")
	}
	if !authx.IsCompanyAdmin(u.Role) {
		return nil, fmt.Errorf("仅可管理公司管理员账号")
	}
	if authx.IsPlatformAdmin(u.Role) {
		return nil, fmt.Errorf("cannot edit platform admin")
	}
	out := &AdminAccountOut{
		UserID: u.UserID, Username: u.Username, Phone: u.Phone,
		UsernameLoginDisabled: u.UsernameLoginDisabled,
		DisplayName: u.DisplayName, Role: u.Role,
	}
	if resetPassword {
		plain, err := l.svcCtx.Users.SetPassword(l.ctx, userID, password)
		if err != nil {
			return nil, err
		}
		out.Password = plain
	}
	if phone != nil {
		if l.phoneLoginOnly() && strings.TrimSpace(*phone) == "" {
			return nil, fmt.Errorf("本部署仅支持手机号登录，不可解绑手机号")
		}
		nu, err := l.svcCtx.Users.BindPhone(l.ctx, userID, *phone)
		if err != nil {
			return nil, err
		}
		out.Phone = nu.Phone
		out.DisplayName = nu.DisplayName
		out.UsernameLoginDisabled = nu.UsernameLoginDisabled
	}
	if disableUsernameLogin != nil {
		nu, err := l.svcCtx.Users.SetUsernameLoginDisabled(l.ctx, userID, *disableUsernameLogin)
		if err != nil {
			return nil, err
		}
		out.Phone = nu.Phone
		out.UsernameLoginDisabled = nu.UsernameLoginDisabled
	}
	return out, nil
}

func (l *PlatformLogic) UpdateTenant(tenantID int64, name, slug string) (*userstore.TenantInfo, error) {
	if _, err := l.requireSuper(); err != nil {
		return nil, err
	}
	return l.svcCtx.Users.UpdateTenant(l.ctx, tenantID, name, slug)
}

func (l *PlatformLogic) GetTenantPerms(tenantID int64) ([]string, error) {
	if _, err := l.requireSuper(); err != nil {
		return nil, err
	}
	if l.svcCtx.TenantPerm == nil {
		return authx.CompanyPermCatalog(), nil
	}
	if _, err := l.svcCtx.Users.GetTenant(l.ctx, tenantID); err != nil {
		return nil, err
	}
	return l.svcCtx.TenantPerm.Get(l.ctx, tenantID)
}

func (l *PlatformLogic) SetTenantPerms(tenantID int64, perms []string) ([]string, error) {
	if _, err := l.requireSuper(); err != nil {
		return nil, err
	}
	if l.svcCtx.TenantPerm == nil {
		return nil, fmt.Errorf("tenant perm store unavailable")
	}
	if _, err := l.svcCtx.Users.GetTenant(l.ctx, tenantID); err != nil {
		return nil, err
	}
	if err := l.svcCtx.TenantPerm.Set(l.ctx, tenantID, perms); err != nil {
		return nil, err
	}
	return l.svcCtx.TenantPerm.Get(l.ctx, tenantID)
}

func (l *PlatformLogic) IssueAdminInvite(tenantID int64) (*invitestore.Invite, error) {
	super, err := l.requireSuper()
	if err != nil {
		return nil, err
	}
	if l.svcCtx.Invites == nil {
		return nil, fmt.Errorf("invite store unavailable")
	}
	if _, err := l.svcCtx.Users.GetTenant(l.ctx, tenantID); err != nil {
		return nil, err
	}
	return l.svcCtx.Invites.Create(l.ctx, tenantID, super.UserID, invitestore.CreateInput{
		Role:      authx.Role管理员,
		MaxUses:   1,
		ExpiresIn: 7 * 24 * time.Hour,
	})
}

// EnterTenant 进入某公司上下文（JWT 仍为超级管理员，但带上 tenant_id）。
func (l *PlatformLogic) EnterTenant(tenantID int64) (*types.TokenResp, error) {
	super, err := l.requireSuper()
	if err != nil {
		return nil, err
	}
	if tenantID <= 0 {
		return nil, fmt.Errorf("tenant_id required")
	}
	t, err := l.svcCtx.Users.GetTenant(l.ctx, tenantID)
	if err != nil {
		return nil, err
	}
	resp, err := l.issue(t.TenantID, super.UserID, authx.Role超级管理员, super.Username, super.DisplayName, 0)
	if err != nil {
		return nil, err
	}
	resp.Phone = super.Phone
	resp.Status = userstore.StatusActive
	resp.TenantName = t.Name
	resp.Message = fmt.Sprintf("已打开「%s」的管理视图（你仍是平台超管，不是该公司账号）", t.Name)
	return resp, nil
}

// ExitTenant 退出公司管理视图，回到平台工作台（tenant_id=0）。
func (l *PlatformLogic) ExitTenant() (*types.TokenResp, error) {
	super, err := l.requireSuper()
	if err != nil {
		return nil, err
	}
	resp, err := l.issue(0, super.UserID, authx.Role超级管理员, super.Username, super.DisplayName, 0)
	if err != nil {
		return nil, err
	}
	resp.Phone = super.Phone
	resp.Status = userstore.StatusActive
	resp.Message = "已回到平台工作台"
	return resp, nil
}

// CompanyEntitlements 本公司可用权限。
func (l *AuthLogic) CompanyEntitlements() ([]string, []authx.PermModule, error) {
	tid := authx.TenantID(l.ctx)
	if tid <= 0 {
		return nil, nil, fmt.Errorf("missing tenant")
	}
	var perms []string
	var err error
	// 超管进入公司后看全量权限模块，便于代管（不受该公司额度裁剪展示）
	if authx.IsPlatformAdmin(authx.Role(l.ctx)) {
		perms = authx.CompanyPermCatalog()
	} else if l.svcCtx.TenantPerm != nil {
		perms, err = l.svcCtx.TenantPerm.Get(l.ctx, tid)
		if err != nil {
			return nil, nil, err
		}
	} else {
		perms = authx.CompanyPermCatalog()
	}
	allow := map[string]struct{}{}
	for _, p := range perms {
		allow[p] = struct{}{}
	}
	var modules []authx.PermModule
	for _, m := range authx.PermModules() {
		var items []authx.PermItem
		for _, it := range m.Items {
			if _, ok := allow[it.Perm]; ok {
				items = append(items, it)
			}
		}
		if len(items) > 0 {
			modules = append(modules, authx.PermModule{Title: m.Title, Items: items})
		}
	}
	return perms, modules, nil
}
