package system

import (
	"context"
	"errors"
	"strings"

	"kra/internal/conf"
)

// Api API实体
type Api struct {
	ID          uint
	Path        string
	Description string
	ApiGroup    string
	Method      string
}

// IgnoreApi 忽略的API
type IgnoreApi struct {
	Path   string
	Method string
}

// CasbinRule Casbin规则
type CasbinRule struct {
	Path   string
	Method string
}

// ApiRepo API仓储接口
type ApiRepo interface {
	Create(ctx context.Context, api *Api) error
	Update(ctx context.Context, api *Api) error
	Delete(ctx context.Context, id uint) error
	DeleteByIds(ctx context.Context, ids []uint) error
	FindByID(ctx context.Context, id uint) (*Api, error)
	FindByPathMethod(ctx context.Context, path, method string) (*Api, error)
	List(ctx context.Context, page, pageSize int, filters map[string]string, orderKey string, desc bool) ([]*Api, int64, error)
	FindAll(ctx context.Context) ([]*Api, error)
	FindByIds(ctx context.Context, ids []uint) ([]*Api, error)
	GetApiGroups(ctx context.Context) ([]string, map[string]string, error)
	CreateIgnoreApi(ctx context.Context, path, method string) error
	DeleteIgnoreApi(ctx context.Context, path, method string) error
	FindAllIgnoreApis(ctx context.Context) ([]*IgnoreApi, error)
}

// CasbinRepo Casbin仓储接口
type CasbinRepo interface {
	ClearCasbin(v int, p ...string) bool
	UpdateCasbinApi(oldPath, newPath, oldMethod, newMethod string) error
	GetPolicyPathByAuthorityId(authorityId uint) []CasbinRule
	FreshCasbin() error
	AddPolicies(rules [][]string) error
	UpdateCasbin(adminAuthorityID, authorityId uint, casbinInfos []CasbinRule) error
	RemoveFilteredPolicy(authorityId string) error
	SyncPolicy(authorityId string, rules [][]string) error
}

// ApiUsecase API用例
type ApiUsecase struct {
	repo          ApiRepo
	casbinRepo    CasbinRepo
	authRepo      AuthorityRepo
	useStrictAuth bool
	routers       []RouterInfo // 内存中的路由信息
}

// RouterInfo 路由信息
type RouterInfo struct {
	Path   string
	Method string
}

// NewApiUsecase 创建API用例
func NewApiUsecase(repo ApiRepo, casbinRepo CasbinRepo, authRepo AuthorityRepo, useStrictAuth conf.UseStrictAuth) *ApiUsecase {
	return &ApiUsecase{
		repo:          repo,
		casbinRepo:    casbinRepo,
		authRepo:      authRepo,
		useStrictAuth: bool(useStrictAuth),
		routers:       make([]RouterInfo, 0),
	}
}

// SetRouters 设置内存中的路由信息
func (uc *ApiUsecase) SetRouters(routers []RouterInfo) {
	uc.routers = routers
}

// CreateApi 创建API
func (uc *ApiUsecase) CreateApi(ctx context.Context, api *Api) error {
	return uc.repo.Create(ctx, api)
}

// UpdateApi 更新API
func (uc *ApiUsecase) UpdateApi(ctx context.Context, api *Api) error {
	// 获取旧记录
	old, err := uc.repo.FindByID(ctx, api.ID)
	if err != nil {
		return err
	}

	// 如果路径或方法变更，更新Casbin
	if old.Path != api.Path || old.Method != api.Method {
		if err := uc.casbinRepo.UpdateCasbinApi(old.Path, api.Path, old.Method, api.Method); err != nil {
			return err
		}
	}

	return uc.repo.Update(ctx, api)
}

// DeleteApi 删除API
func (uc *ApiUsecase) DeleteApi(ctx context.Context, id uint) error {
	api, err := uc.repo.FindByID(ctx, id)
	if err != nil {
		return err
	}

	if err := uc.repo.Delete(ctx, id); err != nil {
		return err
	}

	// 清除Casbin规则
	uc.casbinRepo.ClearCasbin(1, api.Path, api.Method)
	return nil
}

// DeleteApisByIds 批量删除API
func (uc *ApiUsecase) DeleteApisByIds(ctx context.Context, ids []uint) error {
	apis, err := uc.repo.FindByIds(ctx, ids)
	if err != nil {
		return err
	}

	if err := uc.repo.DeleteByIds(ctx, ids); err != nil {
		return err
	}

	// 清除Casbin规则
	for _, api := range apis {
		uc.casbinRepo.ClearCasbin(1, api.Path, api.Method)
	}
	return nil
}

// GetApiById 根据ID获取API
func (uc *ApiUsecase) GetApiById(ctx context.Context, id uint) (*Api, error) {
	return uc.repo.FindByID(ctx, id)
}

// GetAPIInfoList 分页获取API列表
func (uc *ApiUsecase) GetAPIInfoList(ctx context.Context, page, pageSize int, filters map[string]string, orderKey string, desc bool) ([]*Api, int64, error) {
	// 验证排序字段
	if orderKey != "" {
		orderMap := map[string]bool{"id": true, "path": true, "api_group": true, "description": true, "method": true}
		if !orderMap[orderKey] {
			return nil, 0, errors.New("非法的排序字段: " + orderKey)
		}
	}
	return uc.repo.List(ctx, page, pageSize, filters, orderKey, desc)
}

// GetApiList 分页获取API列表（简化版本）
func (uc *ApiUsecase) GetApiList(ctx context.Context, page, pageSize int, filters map[string]interface{}) ([]*Api, int64, error) {
	// 转换 filters
	strFilters := make(map[string]string)
	for k, v := range filters {
		if s, ok := v.(string); ok {
			strFilters[k] = s
		}
	}
	return uc.repo.List(ctx, page, pageSize, strFilters, "", false)
}

// GetAllApis 获取所有API（根据权限过滤）
func (uc *ApiUsecase) GetAllApis(ctx context.Context, authorityID uint) ([]*Api, error) {
	parentAuthorityID, err := uc.authRepo.GetParentAuthorityID(ctx, authorityID)
	if err != nil {
		return nil, err
	}

	apis, err := uc.repo.FindAll(ctx)
	if err != nil {
		return nil, err
	}

	// 如果是顶级角色或不使用严格权限，返回所有API
	if parentAuthorityID == 0 || !uc.useStrictAuth {
		return apis, nil
	}

	// 根据Casbin规则过滤
	paths := uc.casbinRepo.GetPolicyPathByAuthorityId(authorityID)
	var authApis []*Api
	for _, api := range apis {
		for _, rule := range paths {
			if rule.Path == api.Path && rule.Method == api.Method {
				authApis = append(authApis, api)
				break
			}
		}
	}
	return authApis, nil
}

// GetApiGroups 获取API分组
func (uc *ApiUsecase) GetApiGroups(ctx context.Context) ([]string, map[string]string, error) {
	return uc.repo.GetApiGroups(ctx)
}

// SyncApi 同步API
func (uc *ApiUsecase) SyncApi(ctx context.Context) (newApis, deleteApis, ignoreApis []*Api, err error) {
	newApis = make([]*Api, 0)
	deleteApis = make([]*Api, 0)
	ignoreApis = make([]*Api, 0)

	// 获取数据库中的API
	apis, err := uc.repo.FindAll(ctx)
	if err != nil {
		return nil, nil, nil, err
	}

	// 获取忽略的API
	ignores, err := uc.repo.FindAllIgnoreApis(ctx)
	if err != nil {
		return nil, nil, nil, err
	}

	for _, ig := range ignores {
		ignoreApis = append(ignoreApis, &Api{
			Path:   ig.Path,
			Method: ig.Method,
		})
	}

	// 过滤掉忽略的路由
	var cacheApis []*Api
	for _, r := range uc.routers {
		ignored := false
		for _, ig := range ignores {
			if ig.Path == r.Path && ig.Method == r.Method {
				ignored = true
				break
			}
		}
		if !ignored {
			cacheApis = append(cacheApis, &Api{
				Path:   r.Path,
				Method: r.Method,
			})
		}
	}

	// 对比：内存中有但数据库没有的 -> 新增
	for _, cache := range cacheApis {
		found := false
		for _, api := range apis {
			if cache.Path == api.Path && cache.Method == api.Method {
				found = true
				break
			}
		}
		if !found {
			newApis = append(newApis, &Api{
				Path:   cache.Path,
				Method: cache.Method,
			})
		}
	}

	// 对比：数据库有但内存没有的 -> 删除
	for _, api := range apis {
		found := false
		for _, cache := range cacheApis {
			if cache.Path == api.Path && cache.Method == api.Method {
				found = true
				break
			}
		}
		if !found {
			deleteApis = append(deleteApis, api)
		}
	}

	return newApis, deleteApis, ignoreApis, nil
}

// IgnoreApi 忽略/取消忽略API
func (uc *ApiUsecase) IgnoreApi(ctx context.Context, path, method string, flag bool) error {
	if flag {
		return uc.repo.CreateIgnoreApi(ctx, path, method)
	}
	return uc.repo.DeleteIgnoreApi(ctx, path, method)
}

// EnterSyncApi 确认同步API
func (uc *ApiUsecase) EnterSyncApi(ctx context.Context, newApis, deleteApis []*Api) error {
	// 创建新API
	for _, api := range newApis {
		if err := uc.repo.Create(ctx, api); err != nil {
			// 忽略重复错误
			if !strings.Contains(err.Error(), "存在相同api") {
				return err
			}
		}
	}

	// 删除旧API
	for _, api := range deleteApis {
		uc.casbinRepo.ClearCasbin(1, api.Path, api.Method)
		existing, err := uc.repo.FindByPathMethod(ctx, api.Path, api.Method)
		if err == nil && existing != nil {
			if err := uc.repo.Delete(ctx, existing.ID); err != nil {
				return err
			}
		}
	}

	return nil
}

// FreshCasbin 刷新Casbin缓存
func (uc *ApiUsecase) FreshCasbin() error {
	return uc.casbinRepo.FreshCasbin()
}
