import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ClsService } from 'nestjs-cls';
import { TenantAwareRepository } from '../../../common/repositories/tenant-aware.repository';
import { QueryQuoteEntity } from '../../../entities/query-quote.entity';

@Injectable()
export class QuoteRepository extends TenantAwareRepository<QueryQuoteEntity> {
  constructor(
    @InjectRepository(QueryQuoteEntity) repo: Repository<QueryQuoteEntity>,
    cls: ClsService,
  ) {
    super(repo, cls);
  }

  async findByQueryId(queryId: string): Promise<QueryQuoteEntity[]> {
    const tenantId = this.getTenantId();
    const quotes = await this.repo.find({
      where: { query_id: queryId, tenant_id: tenantId, is_deleted: false },
      relations: {
        hotel_items: {
          hotel: true,
          periods: true,
          extras: true,
        },

        transport_items: {
          transport_service: true,
        },

        activity_items: {
          activity: true,
          ticket: true,
        },

        special_items: true,
        selling_currency: true,
      },
      order: { quote_number: 'ASC' },
    });

    // Sort child items by sort_order and filter soft-deleted
    for (const q of quotes) {
      if (q.hotel_items) {
        q.hotel_items = q.hotel_items
          .filter((i) => !i.is_deleted)
          .sort((a, b) => (a.check_in_date || '').localeCompare(b.check_in_date || ''));
        for (const hi of q.hotel_items) {
          if (hi.periods)
            hi.periods = hi.periods
              .filter((p) => !p.is_deleted)
              .sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
          if (hi.extras)
            hi.extras = hi.extras
              .filter((e) => !e.is_deleted)
              .sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
        }
      }
      if (q.transport_items)
        q.transport_items = q.transport_items
          .filter((i) => !i.is_deleted)
          .sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
      if (q.activity_items)
        q.activity_items = q.activity_items
          .filter((i) => !i.is_deleted)
          .sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
      if (q.special_items)
        q.special_items = q.special_items
          .filter((i) => !i.is_deleted)
          .sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
    }

    return quotes;
  }

  async findByIdWithRelations(id: string): Promise<QueryQuoteEntity | null> {
    const tenantId = this.getTenantId();
    return this.repo.findOne({
      where: { id, tenant_id: tenantId, is_deleted: false },
      relations: {
        hotel_items: {
          hotel: true,
          periods: true,
          extras: true,
        },

        transport_items: {
          transport_service: true,
        },

        activity_items: {
          activity: true,
          ticket: true,
        },

        special_items: true,
        selling_currency: true,
      },
    });
  }

  async unselectAllForQuery(queryId: string): Promise<void> {
    const tenantId = this.getTenantId();
    await this.repo.update({ query_id: queryId, tenant_id: tenantId }, { is_selected: false });
  }

  async markSelected(quoteId: string): Promise<void> {
    await this.repo.update(quoteId, { is_selected: true });
  }

  async findSummariesByQueryId(queryId: string): Promise<QueryQuoteEntity[]> {
    const tenantId = this.getTenantId();
    return this.repo.find({
      where: { query_id: queryId, tenant_id: tenantId, is_deleted: false },
      // updated_at is surfaced so the QuoteTabsNav can render a "last
      // updated" stamp next to each tab's amount — gives ops a quick
      // sense of which variant is freshest before opening it.
      select: {
        id: true,
        query_id: true,
        label: true,
        quote_number: true,
        is_selected: true,
        hotel_total: true,
        transport_total: true,
        activity_total: true,
        special_total: true,
        grand_total: true,
        pricing_strategy: true,
        selling_currency_id: true,
        selling_total: true,
        updated_at: true,
      },
      relations: {
        selling_currency: true,
      },
      order: { quote_number: 'ASC' },
    });
  }

  async getNextQuoteNumber(queryId: string): Promise<number> {
    const tenantId = this.getTenantId();
    const result = await this.repo
      .createQueryBuilder('q')
      .select('MAX(q.quote_number)', 'max')
      .where('q.query_id = :queryId', { queryId })
      .andWhere('q.tenant_id = :tenantId', { tenantId })
      .getRawOne();
    return (result?.max || 0) + 1;
  }
}
