import { HttpError, type RequestContext } from '../../core/http.js';
import { queryOne } from '../../core/db.js';
import { tenantIdFrom, userIdFrom } from '../../core/request.js';

const TENANT_ADMIN_ROLES = new Set([
  'tenant_owner',
  'tenant_admin',
  'tenant_operator',
  'teacher',
  'sales',
  'agent',
]);
const ROLE_PERMISSION_DEFAULTS: Record<string, string[]> = {
  tenant_owner: ['*'],
  tenant_admin: ['*'],
  tenant_operator: ['dashboard:read', 'content:*', 'marketing:*', 'badges:*', 'notifications:read', 'codes:read', 'coupons:read', 'referral:read', 'commission:read', 'crm:read'],
  teacher: ['content:*', 'classes:read', 'students:read', 'students:notes:*', 'students:followups:*', 'students:supervision:*'],
  sales: ['codes:*', 'coupons:read', 'coupons:write', 'referral:*', 'commission:self'],
  agent: ['codes:read', 'coupons:read', 'referral:self', 'commission:self'],
  student: [],
};

export interface TenantAdminAuth {
  tenantId: string;
  userId: string;
  role: string;
  roleTemplateId: string | null;
  roleTemplateCode: string | null;
  roleTemplateName: string | null;
  permissions: Record<string, unknown>;
  templatePermissions: Record<string, unknown>;
  menuPermissions: Record<string, unknown>;
  modulePermissions: Record<string, unknown>;
  fieldPermissions: Record<string, unknown>;
  dataScope: Record<string, unknown>;
}

function permissionKeys(permission: string) {
  const parts = permission.split(':').filter(Boolean);
  const keys = [permission];
  for (let i = parts.length - 1; i >= 1; i -= 1) {
    keys.push(`${parts.slice(0, i).join(':')}:*`);
  }
  keys.push('*');
  return keys;
}

function explicitPermission(permissions: Record<string, unknown>, permission: string) {
  for (const key of permissionKeys(permission)) {
    const value = permissions[key];
    if (typeof value === 'boolean') return value;
  }
  return null;
}

export function hasTenantPermission(auth: TenantAdminAuth, permission: string) {
  const explicit = explicitPermission(auth.permissions, permission);
  if (explicit !== null) return explicit;

  const templateExplicit = explicitPermission(auth.templatePermissions, permission);
  if (templateExplicit !== null) return templateExplicit;

  const defaults = ROLE_PERMISSION_DEFAULTS[auth.role] || [];
  return defaults.some(defaultPermission => {
    if (defaultPermission === '*') return true;
    if (defaultPermission === permission) return true;
    if (defaultPermission.endsWith(':*')) {
      return permission.startsWith(defaultPermission.slice(0, -1));
    }
    return false;
  });
}

export function requireTenantPermission(auth: TenantAdminAuth, permission: string) {
  if (!hasTenantPermission(auth, permission)) {
    throw new HttpError(403, `Tenant permission is required: ${permission}`, 'TENANT_PERMISSION_REQUIRED');
  }
}

export function tenantPermissionCatalog() {
  return {
    permissions: [
      { key: 'tenant:overview:read', label: '租户概览' },
      { key: 'dashboard:read', label: '数据看板查看' },
      { key: 'tenant:branding:write', label: '品牌配置' },
      { key: 'tenant:theme:read', label: '主题查看' },
      { key: 'tenant:theme:write', label: '主题预览/发布' },
      { key: 'tenant:settings:write', label: '公开设置' },
      { key: 'tenant:domains:read', label: '域名查看' },
      { key: 'tenant:domains:write', label: '域名管理' },
      { key: 'tenant:payment:read', label: '商户配置查看' },
      { key: 'tenant:payment:write', label: '商户配置管理' },
      { key: 'tenant:reconciliation:read', label: '资金对账查看' },
      { key: 'tenant:reconciliation:write', label: '资金对账导入' },
      { key: 'tenant:reconciliation:review', label: '资金差错复核' },
      { key: 'tenant:reconciliation:download', label: '官方账单下载' },
      { key: 'tenant:refund:read', label: '退款查看' },
      { key: 'tenant:refund:write', label: '退款申请/处理' },
      { key: 'tenant:refund:review', label: '退款审核' },
      { key: 'tenant:auth:read', label: '登录配置查看' },
      { key: 'tenant:auth:write', label: '登录配置管理' },
      { key: 'tenant:secrets:read', label: '密钥掩码查看' },
      { key: 'tenant:secrets:write', label: '密钥轮换' },
      { key: 'marketing:read', label: '活动内容查看' },
      { key: 'marketing:write', label: '活动内容管理' },
      { key: 'marketing:points:read', label: '积分任务/兑换查看' },
      { key: 'marketing:points:write', label: '积分任务/兑换管理' },
      { key: 'marketing:points:risk:read', label: '积分风控查看' },
      { key: 'notifications:read', label: '用户站内通知查看' },
      { key: 'badges:read', label: '勋章查看' },
      { key: 'badges:write', label: '勋章管理' },
      { key: 'badges:grant', label: '勋章发放' },
      { key: 'codes:read', label: '激活码查看' },
      { key: 'codes:write', label: '激活码管理' },
      { key: 'coupons:read', label: '优惠券查看' },
      { key: 'coupons:write', label: '优惠券管理' },
      { key: 'coupons:redemptions:read', label: '优惠券核销明细/报表' },
      { key: 'referral:read', label: '客资全局查看' },
      { key: 'referral:self', label: '本人客资查看' },
      { key: 'referral:write', label: '客资归属管理' },
      { key: 'commission:self', label: '本人分佣查看' },
      { key: 'commission:read', label: '分佣结算查看' },
      { key: 'commission:write', label: '分佣结算生成' },
      { key: 'commission:review', label: '分佣结算审核/打款' },
      { key: 'crm:read', label: 'CRM 队列查看' },
      { key: 'crm:write', label: 'CRM 入队和重试' },
      { key: 'feedback:read', label: '反馈查看' },
      { key: 'feedback:write', label: '反馈处理' },
      { key: 'classes:read', label: '班级查看' },
      { key: 'classes:write', label: '班级管理' },
      { key: 'students:read', label: '学生查看' },
      { key: 'students:write', label: '学生管理' },
      { key: 'students:bulk:write', label: '学生批量导入/分班' },
      { key: 'students:status:write', label: '学生禁用/恢复' },
      { key: 'students:notes:read', label: '学生备注查看' },
      { key: 'students:notes:write', label: '学生备注管理' },
      { key: 'students:followups:read', label: '学生跟进任务查看' },
      { key: 'students:followups:write', label: '学生跟进任务管理' },
      { key: 'students:supervision:read', label: '学习督导预览' },
      { key: 'students:supervision:write', label: '学习督导生成' },
      { key: 'members:read', label: '成员查看' },
      { key: 'members:write', label: '成员管理' },
      { key: 'roles:read', label: '角色模板查看' },
      { key: 'roles:write', label: '角色模板管理' },
      { key: 'audit:read', label: '审计日志查看' },
      { key: 'content:*', label: '内容维护' },
    ],
    menuGroups: [
      { key: 'dashboard', label: '数据看板' },
      { key: 'content', label: '题库内容' },
      { key: 'students', label: '学生管理' },
      { key: 'teachers', label: '教师/班级' },
      { key: 'marketing', label: '营销中心' },
      { key: 'sales', label: '销售/代理' },
      { key: 'crm', label: 'CRM' },
      { key: 'commerce', label: '订单/权益' },
      { key: 'settings', label: '租户设置' },
      { key: 'audit', label: '审计日志' },
    ],
    fieldGroups: [
      { key: 'student.phone', label: '学生手机号' },
      { key: 'student.wechat', label: '学生微信' },
      { key: 'student.exam_intent', label: '考试意向' },
      { key: 'order.amount', label: '订单金额' },
      { key: 'referral.owner', label: '客资归属' },
      { key: 'payment.secret_mask', label: '商户密钥掩码' },
    ],
    roleDefaults: ROLE_PERMISSION_DEFAULTS,
  };
}

export async function requireTenantAdmin(ctx: RequestContext): Promise<TenantAdminAuth> {
  const tenantId = await tenantIdFrom(ctx);
  const userId = await userIdFrom(ctx);

  const membership = await queryOne<{
    role: string;
    roleTemplateId: string | null;
    roleTemplateCode: string | null;
    roleTemplateName: string | null;
    permissions: Record<string, unknown>;
    templatePermissions: Record<string, unknown>;
    menuPermissions: Record<string, unknown>;
    modulePermissions: Record<string, unknown>;
    fieldPermissions: Record<string, unknown>;
    dataScope: Record<string, unknown>;
  }>(
    `
    select tm.role, tm.permissions,
           tm.role_template_id as "roleTemplateId",
           rt.code as "roleTemplateCode",
           rt.name as "roleTemplateName",
           coalesce(rt.permissions, '{}'::jsonb) as "templatePermissions",
           coalesce(rt.menu_permissions, '{}'::jsonb) as "menuPermissions",
           coalesce(rt.module_permissions, '{}'::jsonb) as "modulePermissions",
           coalesce(rt.field_permissions, '{}'::jsonb) as "fieldPermissions",
           coalesce(rt.data_scope, '{}'::jsonb) as "dataScope"
    from public.tenant_memberships tm
    left join public.tenant_role_templates rt
      on rt.id = tm.role_template_id
     and rt.tenant_id = tm.tenant_id
     and rt.status = 'active'
    where tm.tenant_id = $1
      and tm.user_id = $2
      and tm.status = 'active'
      and tm.role = any($3::text[])
    order by case role
      when 'tenant_owner' then 1
      when 'tenant_admin' then 2
      else 9
    end
    limit 1
    `,
    [tenantId, userId, Array.from(TENANT_ADMIN_ROLES)],
  );

  if (!membership) {
    throw new HttpError(403, 'Tenant admin access is required', 'TENANT_ADMIN_REQUIRED');
  }

  return {
    tenantId,
    userId,
    role: membership.role,
    roleTemplateId: membership.roleTemplateId,
    roleTemplateCode: membership.roleTemplateCode,
    roleTemplateName: membership.roleTemplateName,
    permissions: membership.permissions || {},
    templatePermissions: membership.templatePermissions || {},
    menuPermissions: membership.menuPermissions || {},
    modulePermissions: membership.modulePermissions || {},
    fieldPermissions: membership.fieldPermissions || {},
    dataScope: membership.dataScope || {},
  };
}
