import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Put,
  Patch,
  Query,
  Req,
} from '@nestjs/common';
import { ApplicationsService } from './applications.service';
import { CreateApplicationDto, UpdateApplicationDto } from './application.dto';
import { Request } from 'express';
import { ApplicantIncome } from '../../database/tenant/entities/applicant-income.entity';
import { ApplicantBusinessIncome } from '../../database/tenant/entities/applicant-business-income.entity';
import { ApplicantPayableInstitution } from '../../database/tenant/entities/applicant-payable-institution.entity';
import { ApplicantFinancialTransaction } from '../../database/tenant/entities/applicant-financial-transaction.entity';
import { ApplicantSaving } from '../../database/tenant/entities/applicant-saving.entity';
import { ApplicantCharge } from '../../database/tenant/entities/applicant-charge.entity';
import { ApplicationRelation } from '../../database/tenant/entities/application-relation.entity';
import { Guarantor } from '../../database/tenant/entities/guarantor.entity';

@Controller('applications')
export class ApplicationsController {
  constructor(private readonly svc: ApplicationsService) {}

  private sub(req: Request) { return (req as any).tenantSubdomain as string; }
  private uid(req: Request) { return (req as any).user?.sub as string | undefined; }

  // ── Application CRUD ──────────────────────────────────────

  @Get()
  async findAll(
    @Req() req: Request,
    @Query('q') q?: string,
    @Query('status') status?: string,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    const data = await this.svc.findAll(this.sub(req), {
      q, status,
      page: page ? +page : 1,
      limit: limit ? +limit : 20,
    });
    return { success: true, data };
  }

  @Get(':id')
  async findOne(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.findOne(this.sub(req), id);
    return { success: true, data };
  }

  @Post()
  async create(@Req() req: Request, @Body() dto: CreateApplicationDto) {
    const data = await this.svc.create(this.sub(req), dto, this.uid(req));
    return { success: true, data };
  }

  @Put(':id')
  async update(@Req() req: Request, @Param('id') id: string, @Body() dto: UpdateApplicationDto) {
    const data = await this.svc.update(this.sub(req), id, dto, this.uid(req));
    return { success: true, data };
  }

  @Patch(':id/status')
  async updateStatus(
    @Req() req: Request,
    @Param('id') id: string,
    @Body('status') status: string,
  ) {
    const data = await this.svc.updateStatus(this.sub(req), id, status, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id')
  async remove(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.remove(this.sub(req), id);
    return { success: true, data };
  }

  // ── Incomes ───────────────────────────────────────────────

  @Get(':id/incomes')
  async getIncomes(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), ApplicantIncome, id);
    return { success: true, data };
  }

  @Post(':id/incomes')
  async addIncome(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), ApplicantIncome, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/incomes/:itemId')
  async updateIncome(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), ApplicantIncome, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/incomes/:itemId')
  async removeIncome(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), ApplicantIncome, id, itemId);
    return { success: true, data };
  }

  // ── Business Incomes ──────────────────────────────────────

  @Get(':id/business-incomes')
  async getBusinessIncomes(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), ApplicantBusinessIncome, id);
    return { success: true, data };
  }

  @Post(':id/business-incomes')
  async addBusinessIncome(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), ApplicantBusinessIncome, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/business-incomes/:itemId')
  async updateBusinessIncome(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), ApplicantBusinessIncome, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/business-incomes/:itemId')
  async removeBusinessIncome(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), ApplicantBusinessIncome, id, itemId);
    return { success: true, data };
  }

  // ── Payable Institutions ──────────────────────────────────

  @Get(':id/payable-institutions')
  async getPayableInstitutions(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), ApplicantPayableInstitution, id);
    return { success: true, data };
  }

  @Post(':id/payable-institutions')
  async addPayableInstitution(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), ApplicantPayableInstitution, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/payable-institutions/:itemId')
  async updatePayableInstitution(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), ApplicantPayableInstitution, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/payable-institutions/:itemId')
  async removePayableInstitution(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), ApplicantPayableInstitution, id, itemId);
    return { success: true, data };
  }

  // ── Financial Transactions ────────────────────────────────

  @Get(':id/financial-transactions')
  async getFinancialTransactions(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), ApplicantFinancialTransaction, id);
    return { success: true, data };
  }

  @Post(':id/financial-transactions')
  async addFinancialTransaction(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), ApplicantFinancialTransaction, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/financial-transactions/:itemId')
  async updateFinancialTransaction(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), ApplicantFinancialTransaction, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/financial-transactions/:itemId')
  async removeFinancialTransaction(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), ApplicantFinancialTransaction, id, itemId);
    return { success: true, data };
  }

  // ── Savings ───────────────────────────────────────────────

  @Get(':id/savings')
  async getSavings(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), ApplicantSaving, id);
    return { success: true, data };
  }

  @Post(':id/savings')
  async addSaving(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), ApplicantSaving, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/savings/:itemId')
  async updateSaving(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), ApplicantSaving, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/savings/:itemId')
  async removeSaving(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), ApplicantSaving, id, itemId);
    return { success: true, data };
  }

  // ── Charges ───────────────────────────────────────────────

  @Get(':id/charges')
  async getCharges(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), ApplicantCharge, id);
    return { success: true, data };
  }

  @Post(':id/charges')
  async addCharge(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), ApplicantCharge, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/charges/:itemId')
  async updateCharge(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), ApplicantCharge, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/charges/:itemId')
  async removeCharge(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), ApplicantCharge, id, itemId);
    return { success: true, data };
  }

  // ── Relations (family members) ────────────────────────────

  @Get(':id/relations')
  async getRelations(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), ApplicationRelation, id);
    return { success: true, data };
  }

  @Post(':id/relations')
  async addRelation(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), ApplicationRelation, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/relations/:itemId')
  async updateRelation(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), ApplicationRelation, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/relations/:itemId')
  async removeRelation(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), ApplicationRelation, id, itemId);
    return { success: true, data };
  }

  // ── Guarantors ────────────────────────────────────────────

  @Get(':id/guarantors')
  async getGuarantors(@Req() req: Request, @Param('id') id: string) {
    const data = await this.svc.getSubItems(this.sub(req), Guarantor, id);
    return { success: true, data };
  }

  @Post(':id/guarantors')
  async addGuarantor(@Req() req: Request, @Param('id') id: string, @Body() body: any) {
    const data = await this.svc.addSubItem(this.sub(req), Guarantor, id, body, this.uid(req));
    return { success: true, data };
  }

  @Put(':id/guarantors/:itemId')
  async updateGuarantor(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string, @Body() body: any) {
    const data = await this.svc.updateSubItem(this.sub(req), Guarantor, id, itemId, body, this.uid(req));
    return { success: true, data };
  }

  @Delete(':id/guarantors/:itemId')
  async removeGuarantor(@Req() req: Request, @Param('id') id: string, @Param('itemId') itemId: string) {
    const data = await this.svc.removeSubItem(this.sub(req), Guarantor, id, itemId);
    return { success: true, data };
  }
}
