import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '@/prisma/prisma.service';
import { CreateBankAccountDto, UpdateBankAccountDto, CreateBankTransactionDto, UpdateBankTransactionStatusDto } from '../dto/bank.dto';

@Injectable()
export class BankService {
  constructor(private prisma: PrismaService) {}

  async createAccount(tenantId: string, dto: CreateBankAccountDto) {
    // Verify complex belongs to tenant
    const complex = await this.prisma.complex.findFirst({
      where: { id: dto.complexId, tenantId },
    });
    if (!complex) throw new NotFoundException('Complex not found');

    if (dto.isDefault) {
      await this.prisma.bankAccount.updateMany({
        where: { complexId: dto.complexId },
        data: { isDefault: false },
      });
    }

    return this.prisma.bankAccount.create({
      data: {
        complexId: dto.complexId,
        bankName: dto.bankName,
        accountName: dto.accountName,
        rib: dto.rib,
        iban: dto.iban,
        initialBalance: dto.initialBalance || 0,
        currency: dto.currency || 'MAD',
        isDefault: dto.isDefault || false,
      },
    });
  }

  async getAccounts(tenantId: string | null, complexId: string) {
    return this.prisma.bankAccount.findMany({
      where: {
        complexId,
        ...(tenantId && { complex: { tenantId } }),
      },
      include: {
        _count: {
          select: { transactions: true }
        }
      },
      orderBy: { createdAt: 'desc' },
    });
  }

  async getAccount(tenantId: string | null, accountId: string) {
    const account = await this.prisma.bankAccount.findFirst({
      where: {
        id: accountId,
        ...(tenantId && { complex: { tenantId } }),
      },
      include: { transactions: { orderBy: { date: 'desc' } } },
    });
    if (!account) throw new NotFoundException('Account not found');
    return account;
  }

  async updateAccount(tenantId: string | null, accountId: string, dto: UpdateBankAccountDto) {
    const account = await this.prisma.bankAccount.findFirst({
      where: { id: accountId, ...(tenantId && { complex: { tenantId } }) },
    });
    if (!account) throw new NotFoundException('Account not found');

    if (dto.isDefault) {
      await this.prisma.bankAccount.updateMany({
        where: { complexId: account.complexId },
        data: { isDefault: false },
      });
    }

    return this.prisma.bankAccount.update({
      where: { id: accountId },
      data: dto,
    });
  }

  async deleteAccount(tenantId: string | null, accountId: string) {
    const account = await this.prisma.bankAccount.findFirst({
      where: { id: accountId, ...(tenantId && { complex: { tenantId } }) },
    });
    if (!account) throw new NotFoundException('Account not found');

    return this.prisma.bankAccount.delete({
      where: { id: accountId },
    });
  }

  // Transactions
  async addTransaction(tenantId: string | null, dto: CreateBankTransactionDto) {
    const account = await this.prisma.bankAccount.findFirst({
      where: { id: dto.bankAccountId, ...(tenantId && { complex: { tenantId } }) },
    });
    if (!account) throw new NotFoundException('Account not found');

    return this.prisma.bankTransaction.create({
      data: {
        bankAccountId: dto.bankAccountId,
        date: new Date(dto.date),
        label: dto.label,
        amount: dto.amount,
        type: dto.type,
        notes: dto.notes,
      },
    });
  }

  async getTransactions(tenantId: string | null, accountId: string) {
    const account = await this.prisma.bankAccount.findFirst({
      where: { id: accountId, ...(tenantId && { complex: { tenantId } }) },
    });
    if (!account) throw new NotFoundException('Account not found');

    return this.prisma.bankTransaction.findMany({
      where: { bankAccountId: accountId },
      orderBy: { date: 'desc' },
    });
  }

  async updateTransactionStatus(tenantId: string | null, transactionId: string, userId: string, dto: UpdateBankTransactionStatusDto) {
    const tx = await this.prisma.bankTransaction.findFirst({
      where: { id: transactionId, ...(tenantId && { bankAccount: { complex: { tenantId } } }) },
    });
    if (!tx) throw new NotFoundException('Transaction not found');

    return this.prisma.bankTransaction.update({
      where: { id: transactionId },
      data: {
        status: dto.status,
        reconciledById: dto.status === 'RECONCILED' ? userId : null,
        reconciledAt: dto.status === 'RECONCILED' ? new Date() : null,
      },
    });
  }
}
