import { Injectable, NotFoundException } from '@nestjs/common';
import { TenantConnectionService } from '../../database/tenant-connection.service';
import { Task } from '../../database/tenant/entities/task.entity';

export interface CreateTaskDto {
  title: string; titleNe?: string;
  description?: string; descriptionNe?: string;
  status?: string; priority?: string; category?: string;
  dueDate?: string; assignedToId?: string; assignedToName?: string;
  officeId?: string; remarks?: string;
}
export type UpdateTaskDto = Partial<CreateTaskDto> & { completedDate?: string };

@Injectable()
export class TasksService {
  constructor(private tenantConn: TenantConnectionService) {}
  private async repo(sub: string) {
    const ds = await this.tenantConn.getTenantDataSource(sub);
    return ds.getRepository(Task);
  }

  async findAll(sub: string, opts: { status?: string; priority?: string; assignedToId?: string; q?: string; page?: number; limit?: number }) {
    const r = await this.repo(sub);
    const { status, priority, assignedToId, q, page = 1, limit = 20 } = opts;
    const qb = r.createQueryBuilder('t')
      .where('t.deletedAt IS NULL')
      .orderBy('CASE t.priority WHEN \'urgent\' THEN 1 WHEN \'high\' THEN 2 WHEN \'medium\' THEN 3 ELSE 4 END', 'ASC')
      .addOrderBy('t.dueDate', 'ASC', 'NULLS LAST')
      .addOrderBy('t.createdAt', 'DESC')
      .skip((page - 1) * limit).take(limit);
    if (status) qb.andWhere('t.status = :status', { status });
    if (priority) qb.andWhere('t.priority = :priority', { priority });
    if (assignedToId) qb.andWhere('t.assignedToId = :assignedToId', { assignedToId });
    if (q) qb.andWhere('(t.title LIKE :q OR t.titleNe LIKE :q OR t.description LIKE :q)', { q: `%${q}%` });
    const [items, total] = await qb.getManyAndCount();
    const summary = await this.summary(sub);
    return { items, total, page, limit, summary };
  }

  async summary(sub: string) {
    const r = await this.repo(sub);
    const qb = r.createQueryBuilder('t').where('t.deletedAt IS NULL');
    const [total, pending, inProgress, done, overdue] = await Promise.all([
      qb.getCount(),
      r.count({ where: { status: 'pending' } }),
      r.count({ where: { status: 'in_progress' } }),
      r.count({ where: { status: 'done' } }),
      r.createQueryBuilder('t').where('t.deletedAt IS NULL').andWhere('t.status != :s', { s: 'done' }).andWhere('t.dueDate < :now', { now: new Date().toISOString().split('T')[0] }).getCount(),
    ]);
    return { total, pending, inProgress, done, overdue };
  }

  async findOne(sub: string, id: string) {
    const r = await this.repo(sub);
    const t = await r.findOne({ where: { id } });
    if (!t) throw new NotFoundException('Task not found');
    return t;
  }

  async create(sub: string, dto: CreateTaskDto, userId?: string, userName?: string) {
    const r = await this.repo(sub);
    const task = r.create({ ...(dto as any), createdById: userId, createdByName: userName });
    return r.save(task);
  }

  async update(sub: string, id: string, dto: UpdateTaskDto) {
    const r = await this.repo(sub);
    const t = await this.findOne(sub, id);
    if (dto.status === 'done' && !t.completedDate) {
      dto.completedDate = new Date().toISOString().split('T')[0];
    }
    Object.assign(t, dto);
    return r.save(t);
  }

  async remove(sub: string, id: string) {
    const r = await this.repo(sub);
    const t = await this.findOne(sub, id);
    await r.softDelete(id);
    return t;
  }
}
