import { Injectable, NotFoundException } from '@nestjs/common';
import { TenantConnectionService } from '../../database/tenant-connection.service';
import { ApplicationComment } from '../../database/tenant/entities/application-comment.entity';
import { ApplicationStatusLog } from '../../database/tenant/entities/application-status-log.entity';
import { ApplicationRecommendation } from '../../database/tenant/entities/application-recommendation.entity';
import { ApplicationForward } from '../../database/tenant/entities/application-forward.entity';
import { ApplicationForwardUser } from '../../database/tenant/entities/application-forward-user.entity';
import { Application } from '../../database/tenant/entities/application.entity';

@Injectable()
export class ApplicationWorkflowService {
  constructor(private tenantConn: TenantConnectionService) {}

  private async ds(sub: string) { return this.tenantConn.getTenantDataSource(sub); }

  async getTimeline(sub: string, applicationId: string) {
    const ds = await this.ds(sub);
    const [comments, statuses, forwards, recommendations] = await Promise.all([
      ds.getRepository(ApplicationComment).find({ where: { applicationId }, order: { createdAt: 'DESC' } }),
      ds.getRepository(ApplicationStatusLog).find({ where: { applicationId }, order: { createdAt: 'DESC' } }),
      ds.getRepository(ApplicationForward).find({ where: { applicationId }, relations: ['users'], order: { createdAt: 'DESC' } }),
      ds.getRepository(ApplicationRecommendation).find({ where: { applicationId }, order: { createdAt: 'DESC' } }),
    ]);
    return { comments, statuses, forwards, recommendations };
  }

  async addComment(sub: string, applicationId: string, dto: any, userId?: string, userName?: string) {
    const ds = await this.ds(sub);
    const r = ds.getRepository(ApplicationComment);
    return r.save(r.create({ ...dto, applicationId, userId, userName }));
  }

  async getComments(sub: string, applicationId: string) {
    const ds = await this.ds(sub);
    return ds.getRepository(ApplicationComment).find({ where: { applicationId }, order: { createdAt: 'DESC' } });
  }

  async deleteComment(sub: string, applicationId: string, id: string) {
    const ds = await this.ds(sub);
    await ds.getRepository(ApplicationComment).delete(id);
    return { id };
  }

  async changeStatus(sub: string, applicationId: string, statusCode: string, comment: string | undefined, userId?: string, userName?: string) {
    const ds = await this.ds(sub);
    await ds.getRepository(Application).update(applicationId, { status: statusCode, updatedBy: userId });
    const logRepo = ds.getRepository(ApplicationStatusLog);
    return logRepo.save(logRepo.create({ applicationId, statusCode, comment, userId, userName }));
  }

  async getStatusHistory(sub: string, applicationId: string) {
    const ds = await this.ds(sub);
    return ds.getRepository(ApplicationStatusLog).find({ where: { applicationId }, order: { createdAt: 'DESC' } });
  }

  async addRecommendation(sub: string, applicationId: string, dto: any, userId?: string, userName?: string) {
    const ds = await this.ds(sub);
    const r = ds.getRepository(ApplicationRecommendation);
    return r.save(r.create({ ...dto, applicationId, recommendedBy: userId, recommendedByName: userName }));
  }

  async getRecommendations(sub: string, applicationId: string) {
    const ds = await this.ds(sub);
    return ds.getRepository(ApplicationRecommendation).find({ where: { applicationId }, order: { createdAt: 'DESC' } });
  }

  async deleteRecommendation(sub: string, applicationId: string, id: string) {
    const ds = await this.ds(sub);
    await ds.getRepository(ApplicationRecommendation).softDelete(id);
    return { id };
  }

  async addForward(sub: string, applicationId: string, dto: { statusType: string; comment?: string; forwardToType?: string; forwardToId?: string; forwardToName?: string; userIds?: string[] }, userId?: string, userName?: string) {
    const ds = await this.ds(sub);
    const fwdRepo = ds.getRepository(ApplicationForward);
    const userRepo = ds.getRepository(ApplicationForwardUser);

    const fwd = await fwdRepo.save(fwdRepo.create({
      applicationId,
      statusType: dto.statusType,
      comment: dto.comment,
      forwardedById: userId,
      forwardedByName: userName,
      forwardToType: dto.forwardToType,
      forwardToId: dto.forwardToId,
      forwardToName: dto.forwardToName,
    }));

    if (dto.userIds?.length) {
      for (const uid of dto.userIds) {
        await userRepo.save(userRepo.create({ applicationId, applicationForwardId: fwd.id, status: 'pending', userId: uid }));
      }
    }
    return fwdRepo.findOne({ where: { id: fwd.id }, relations: ['users'] });
  }

  async getForwards(sub: string, applicationId: string) {
    const ds = await this.ds(sub);
    return ds.getRepository(ApplicationForward).find({ where: { applicationId }, relations: ['users'], order: { createdAt: 'DESC' } });
  }
}
