import { Injectable, NotFoundException } from '@nestjs/common';
import { TenantConnectionService } from '../../database/tenant-connection.service';
import { MortgageAppraisal } from '../../database/tenant/entities/mortgage-appraisal.entity';
import { MortgageAppraisalLand } from '../../database/tenant/entities/mortgage-appraisal-land.entity';
import { Inject } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';

@Injectable()
export class MortgageAppraisalService {
  constructor(
    private tenantConn: TenantConnectionService,
    @Inject(REQUEST) private request: Request,
  ) {}

  private sub() { return (this.request as any).tenantSubdomain as string; }
  private async ds() { return this.tenantConn.getTenantDataSource(this.sub()); }

  async list(q?: string, applicationId?: string, page = 1, limit = 20) {
    const ds = await this.ds();
    const r = ds.getRepository(MortgageAppraisal);
    const qb = r.createQueryBuilder('ma').where('ma.deletedAt IS NULL').orderBy('ma.createdAt', 'DESC');
    if (q) qb.andWhere('(ma.memberName LIKE :q OR ma.district LIKE :q)', { q: `%${q}%` });
    if (applicationId) qb.andWhere('ma.applicationId = :applicationId', { applicationId });
    const total = await qb.getCount();
    const items = await qb.skip((page - 1) * limit).take(limit).getMany();
    return { items, total, page, limit };
  }

  async findOne(id: string) {
    const ds = await this.ds();
    const appraisal = await ds.getRepository(MortgageAppraisal).findOne({ where: { id } });
    if (!appraisal) throw new NotFoundException('Mortgage appraisal not found');
    const lands = await ds.getRepository(MortgageAppraisalLand).find({ where: { mortgageAppraisalId: id } });
    return { ...appraisal, lands };
  }

  async create(dto: any) {
    const ds = await this.ds();
    const r = ds.getRepository(MortgageAppraisal);
    const { lands, ...rest } = dto;
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const appraisal = (await r.save(r.create({ ...rest, status: rest.status ?? 'draft' }) as any)) as unknown as MortgageAppraisal;
    if (lands && Array.isArray(lands)) {
      const lr = ds.getRepository(MortgageAppraisalLand);
      for (const l of lands) {
        await lr.save(lr.create({ ...l, mortgageAppraisalId: appraisal.id }) as any);
      }
    }
    return this.findOne(appraisal.id);
  }

  async update(id: string, dto: any) {
    const ds = await this.ds();
    const r = ds.getRepository(MortgageAppraisal);
    const e = await r.findOne({ where: { id } });
    if (!e) throw new NotFoundException();
    const { lands, ...rest } = dto;
    await r.save(Object.assign(e, rest));
    if (lands && Array.isArray(lands)) {
      const lr = ds.getRepository(MortgageAppraisalLand);
      await lr.delete({ mortgageAppraisalId: id });
      for (const l of lands) {
        await lr.save(lr.create({ ...l, mortgageAppraisalId: id }) as any);
      }
    }
    return this.findOne(id);
  }

  async remove(id: string) {
    const ds = await this.ds();
    await ds.getRepository(MortgageAppraisal).softDelete(id);
    return { id };
  }

  async addLand(appraisalId: string, dto: any) {
    const ds = await this.ds();
    const lr = ds.getRepository(MortgageAppraisalLand);
    return lr.save(lr.create({ ...dto, mortgageAppraisalId: appraisalId }) as any);
  }

  async updateLand(landId: string, dto: any) {
    const ds = await this.ds();
    const lr = ds.getRepository(MortgageAppraisalLand);
    const e = await lr.findOne({ where: { id: landId } });
    if (!e) throw new NotFoundException();
    return lr.save(Object.assign(e, dto));
  }

  async removeLand(landId: string) {
    const ds = await this.ds();
    await ds.getRepository(MortgageAppraisalLand).delete({ id: landId });
    return { id: landId };
  }
}
