package handler

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"aijianzhan/platform/internal/authx"
	"aijianzhan/platform/internal/logic/applogic"
	"aijianzhan/platform/internal/svc"
	"aijianzhan/platform/internal/userstore"

	"github.com/zeromicro/go-zero/rest/httpx"
	"github.com/zeromicro/go-zero/rest/pathvar"
)

func platformListTenantsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		list, err := l.ListTenants()
		if err != nil {
			authx.WriteError(w, http.StatusForbidden, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"items": list})
	}
}

func platformCreateTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var body struct {
			Name            string `json:"name"`
			Slug            string `json:"slug"`
			AdminPhone      string `json:"admin_phone"`
			WithAdminInvite *bool  `json:"with_admin_invite"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		withInvite := false
		if body.WithAdminInvite != nil {
			withInvite = *body.WithAdminInvite
		}
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		res, err := l.CreateTenant(body.Name, body.Slug, withInvite, body.AdminPhone)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, res)
	}
}

func platformUpdateTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		var body struct {
			Name string `json:"name"`
			Slug string `json:"slug"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		t, err := l.UpdateTenant(id, body.Name, body.Slug)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, t)
	}
}

func platformAdminInviteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		inv, err := l.IssueAdminInvite(id)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, inv)
	}
}

func platformAdminAccountHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		var body struct {
			Phone string `json:"phone"`
		}
		_ = json.NewDecoder(r.Body).Decode(&body)
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		acc, err := l.IssueAdminAccount(id, body.Phone)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		_ = svcCtx.Audit.Log(r.Context(), id, authx.UserID(r.Context()), "platform.admin_account", acc.Username)
		httpx.OkJson(w, map[string]any{"admin_account": acc})
	}
}

func platformListAdminsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		items, err := l.ListCompanyAdmins(id)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"items": items})
	}
}

func platformUpdateAdminHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		tid, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		uid, _ := strconv.ParseInt(pathvar.Vars(r)["uid"], 10, 64)
		var body struct {
			ResetPassword         *bool   `json:"reset_password"`
			Password              string  `json:"password"`
			Phone                 *string `json:"phone"`
			DisableUsernameLogin  *bool   `json:"disable_username_login"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		reset := body.ResetPassword != nil && *body.ResetPassword
		if !reset && body.Phone == nil && body.DisableUsernameLogin == nil {
			authx.WriteError(w, http.StatusBadRequest, "请指定重置密码、更新手机号或禁用用户名登录")
			return
		}
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		acc, err := l.UpdateCompanyAdmin(tid, uid, reset, body.Password, body.Phone, body.DisableUsernameLogin)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		_ = svcCtx.Audit.Log(r.Context(), tid, authx.UserID(r.Context()), "platform.update_admin", acc.Username)
		httpx.OkJson(w, map[string]any{"admin_account": acc})
	}
}

func platformEnterTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		resp, err := l.EnterTenant(id)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		_ = svcCtx.Audit.Log(r.Context(), id, resp.UserID, "platform.enter_tenant", resp.Message)
		httpx.OkJson(w, resp)
	}
}

func platformExitTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		resp, err := l.ExitTenant()
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		_ = svcCtx.Audit.Log(r.Context(), 0, resp.UserID, "platform.exit_tenant", resp.Message)
		httpx.OkJson(w, resp)
	}
}

func platformPermModulesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if !authx.IsPlatformAdmin(authx.Role(r.Context())) {
			authx.WriteError(w, http.StatusForbidden, "需要超级管理员")
			return
		}
		httpx.OkJson(w, map[string]any{
			"modules":  authx.PermModules(),
			"catalog":  authx.CompanyPermCatalog(),
			"platform": []string{authx.Perm管理租户},
		})
	}
}

func platformGetTenantPermsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		perms, err := l.GetTenantPerms(id)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"tenant_id": id, "permissions": perms, "total": len(authx.CompanyPermCatalog())})
	}
}

func platformSetTenantPermsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		var body struct {
			Permissions []string `json:"permissions"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		perms, err := l.SetTenantPerms(id, body.Permissions)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"tenant_id": id, "permissions": perms, "total": len(authx.CompanyPermCatalog())})
	}
}

func companyEntitlementsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		l := applogic.NewAuthLogic(r.Context(), svcCtx)
		perms, modules, err := l.CompanyEntitlements()
		if err != nil {
			authx.WriteError(w, http.StatusForbidden, err.Error())
			return
		}
		httpx.OkJson(w, map[string]any{"permissions": perms, "modules": modules})
	}
}

func memberListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		list, err := l.List()
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		items := make([]map[string]any, 0, len(list))
		for _, u := range list {
			items = append(items, map[string]any{
				"user_id":      u.UserID,
				"username":     u.Username,
				"phone":        u.Phone,
				"display_name": u.DisplayName,
				"role":         u.Role,
				"org_unit_id":  u.OrgUnitID,
				"status":       u.Status,
				"created_at":   u.CreatedAt,
			})
		}
		httpx.OkJson(w, map[string]any{"items": items})
	}
}

func memberCreateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		var body struct {
			Password    string `json:"password"`
			DisplayName string `json:"display_name"`
			Role        string `json:"role"`
			OrgUnitID   int64  `json:"org_unit_id"`
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		u, plain, err := l.Create(body.Password, body.DisplayName, body.Role, body.OrgUnitID)
		if err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		_ = svcCtx.Audit.Log(r.Context(), authx.TenantID(r.Context()), authx.UserID(r.Context()),
			"member.create", "创建成员 "+u.Username)
		httpx.OkJson(w, map[string]any{
			"user_id":      u.UserID,
			"username":     u.Username,
			"display_name": u.DisplayName,
			"role":         u.Role,
			"org_unit_id":  u.OrgUnitID,
			"status":       u.Status,
			"password":     plain,
		})
	}
}

func memberUpdateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
		var body struct {
			Role      string  `json:"role"`
			OrgUnitID int64   `json:"org_unit_id"`
			Status    string  `json:"status"`
			Phone     *string `json:"phone"` // 传则绑定/更换；传 "" 解绑
		}
		if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
			authx.WriteError(w, http.StatusBadRequest, err.Error())
			return
		}
		l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
		var u *userstore.User
		var err error
		if body.Phone != nil {
			u, err = l.SetPhone(id, *body.Phone)
			if err != nil {
				authx.WriteError(w, http.StatusBadRequest, err.Error())
				return
			}
			_ = svcCtx.Audit.Log(r.Context(), authx.TenantID(r.Context()), authx.UserID(r.Context()),
				"member.bind_phone", fmt.Sprintf("成员 #%d phone=%s", id, u.Phone))
		}
		// 仅改手机时不必强制带 role/status；若其它字段有值则再 Update
		if body.Role != "" || body.Status != "" || body.OrgUnitID != 0 || body.Phone == nil {
			u, err = l.Update(id, body.Role, body.OrgUnitID, body.Status)
			if err != nil {
				authx.WriteError(w, http.StatusBadRequest, err.Error())
				return
			}
		}
		if u == nil {
			authx.WriteError(w, http.StatusBadRequest, "nothing to update")
			return
		}
		httpx.OkJson(w, map[string]any{
			"user_id":      u.UserID,
			"username":     u.Username,
			"phone":        u.Phone,
			"display_name": u.DisplayName,
			"role":         u.Role,
			"org_unit_id":  u.OrgUnitID,
			"status":       u.Status,
		})
	}
}
