import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import type { AgentToolContext } from '../agent-tools/agent-tool.types';
import type { StudentAccessScope } from '../students/student-access-scope';
import { StudentAccessScopeFactory } from '../students/student-access-scope.factory';

export interface PendingTask {
  key: string;
  label: string;
  entity: string;
  permission: string;
  workflowKeys: string[];
  count: number | null;
  restricted?: boolean;
  detail?: string;
}

interface TaskDefinition {
  key: string;
  label: string;
  entity: string;
  permission: string;
  workflowKeys: string[];
  teacherRestricted?: boolean;
  sql: (scope: StudentAccessScope) => { sql: string; params: unknown[] };
}

function can(context: AgentToolContext, permission: string): boolean {
  return context.isSuperAdmin || context.permissions.includes(permission);
}

function today(): string {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

function inDays(days: number): string {
  const date = new Date();
  date.setDate(date.getDate() + days);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}

const TASKS: readonly TaskDefinition[] = [
  {
    key: 'students_without_class',
    label: '未分班学生',
    entity: 'student',
    permission: 'student:view',
    workflowKeys: ['student_teaching'],
    teacherRestricted: true,
    sql: () => ({
      sql: `
        SELECT COUNT(*) AS cnt FROM students s
        WHERE s.status = 'active'
          AND NOT EXISTS (
            SELECT 1 FROM class_student cs
            WHERE cs.student_id = s.id AND cs.status = 'active'
          )
      `,
      params: [],
    }),
  },
  {
    key: 'students_without_checkin',
    label: '已建档未入住学生',
    entity: 'occupancy',
    permission: 'occupancy:view',
    workflowKeys: ['dormitory_billing'],
    sql: (scope) => ({
      sql: `
        SELECT COUNT(DISTINCT s.id) AS cnt FROM students s
        INNER JOIN class_student cs ON cs.student_id = s.id AND cs.status = 'active'
        LEFT JOIN occupancies o ON o.student_id = s.id AND o.status = 'active'
        WHERE s.status = 'active'
          ${scope.type === 'teacher' ? 'AND cs.class_id IN (SELECT ct.class_id FROM class_teacher ct WHERE ct.user_id = ?)' : ''}
          AND o.id IS NULL
      `,
      params: scope.type === 'teacher' ? [scope.userId] : [],
    }),
  },
  {
    key: 'occupancies_without_bill',
    label: '在住但未生成账单',
    entity: 'bill',
    permission: 'bill:view',
    workflowKeys: ['dormitory_billing'],
    sql: (scope) => ({
      sql: `
        SELECT COUNT(DISTINCT o.id) AS cnt FROM occupancies o
        ${scope.type === 'teacher' ? 'INNER JOIN class_student cs ON cs.student_id = o.student_id AND cs.status = \'active\'' : ''}
        LEFT JOIN bills b ON b.student_id = o.student_id
        WHERE o.status = 'active'
          ${scope.type === 'teacher' ? 'AND cs.class_id IN (SELECT ct.class_id FROM class_teacher ct WHERE ct.user_id = ?)' : ''}
          AND b.id IS NULL
      `,
      params: scope.type === 'teacher' ? [scope.userId] : [],
    }),
  },
  {
    key: 'rentals_without_contract',
    label: '租赁未归档合同',
    entity: 'rental',
    permission: 'rental:view',
    workflowKeys: ['classroom_rental'],
    sql: () => ({
      sql: `
        SELECT COUNT(*) AS cnt FROM classroom_rentals r
        WHERE r.status = 'active' AND r.contract_path IS NULL
      `,
      params: [],
    }),
  },
  {
    key: 'rentals_ending_soon',
    label: '七天内到期租赁',
    entity: 'rental',
    permission: 'rental:view',
    workflowKeys: ['classroom_rental'],
    sql: () => ({
      sql: `
        SELECT COUNT(*) AS cnt FROM classroom_rentals r
        WHERE r.status = 'active' AND r.end_date BETWEEN ? AND ?
      `,
      params: [today(), inDays(7)],
    }),
  },
];

/**
 * 业务完成度查询：按权限与数据范围返回“待办”计数，供 Agent 在
 * 写入/导入前核实前置数据、完成后给出有数据支撑的下一步建议。
 */
@Injectable()
export class PendingTasksService {
  constructor(
    private readonly dataSource: DataSource,
    private readonly scopeFactory: StudentAccessScopeFactory,
  ) {}

  async getPendingTasks(
    context: AgentToolContext,
    workflowKey?: string,
  ): Promise<PendingTask[]> {
    const scope = this.scopeFactory.buildScope(context);
    const tasks: PendingTask[] = [];
    for (const definition of TASKS) {
      if (!can(context, definition.permission)) continue;
      if (workflowKey && !definition.workflowKeys.includes(workflowKey)) continue;
      if (definition.teacherRestricted && scope.type === 'teacher') {
        tasks.push({
          key: definition.key,
          label: definition.label,
          entity: definition.entity,
          permission: definition.permission,
          workflowKeys: definition.workflowKeys,
          count: null,
          restricted: true,
          detail: '当前角色数据范围不适合统计该待办，建议由教务/运营角色处理',
        });
        continue;
      }
      const { sql, params } = definition.sql(scope);
      const rows = await this.dataSource.query(sql, params);
      const count = Number((rows as Array<Record<string, unknown>>)[0]?.cnt ?? 0);
      tasks.push({
        key: definition.key,
        label: definition.label,
        entity: definition.entity,
        permission: definition.permission,
        workflowKeys: definition.workflowKeys,
        count,
      });
    }
    return tasks;
  }

}
