import {
  Injectable,
  ConflictException,
  NotFoundException,
} from '@nestjs/common';
import { ActivityPricingRepository } from './repositories/activity-pricing.repository';
import { CreateActivityPricingDto, UpdateActivityPricingDto } from './dto';
import { serviceMessages } from '../../common/constants/messages';

const MSG = serviceMessages('Activity pricing');

@Injectable()
export class ActivityPricingService {
  constructor(private readonly repo: ActivityPricingRepository) {}

  async findByDestination(destinationId: string, currencyId?: string) {
    return this.repo.findByDestinationAndCurrency(destinationId, currencyId);
  }

  async findPaginated(query: { destinationId?: string; currencyId?: string; search?: string; page?: number; limit?: number }) {
    return this.repo.findPaginatedByActivities(query);
  }

  async findById(id: string) {
    const item = await this.repo.findById(id);
    if (!item) throw new NotFoundException(MSG.NOT_FOUND);
    return item;
  }

  async create(dto: CreateActivityPricingDto) {
    const existing = await this.repo.findExisting(dto.activity_id, dto.ticket_id || null, dto.age_group, dto.currency_id);
    if (existing) throw new ConflictException('Pricing for this activity + ticket + age group + currency already exists');

    const item = await this.repo.save({
      destination_id: dto.destination_id,
      activity_id: dto.activity_id,
      ticket_id: dto.ticket_id || null,
      age_group: dto.age_group,
      currency_id: dto.currency_id,
      default_price: dto.default_price ?? null,
      season_1_price: dto.season_1_price ?? null,
      season_2_price: dto.season_2_price ?? null,
      season_3_price: dto.season_3_price ?? null,
      season_4_price: dto.season_4_price ?? null,
      season_5_price: dto.season_5_price ?? null,
    });

    return { id: item.id, message: MSG.CREATED };
  }

  async bulkSave(items: CreateActivityPricingDto[]) {
    const results: any[] = [];
    for (const dto of items) {
      const existing = await this.repo.findExisting(dto.activity_id, dto.ticket_id || null, dto.age_group, dto.currency_id);
      if (existing) {
        const updateData: any = {};
        for (const field of ['default_price', 'season_1_price', 'season_2_price', 'season_3_price', 'season_4_price', 'season_5_price']) {
          if ((dto as any)[field] !== undefined) updateData[field] = (dto as any)[field];
        }
        await this.repo.update(existing.id, updateData);
        results.push({ id: existing.id, action: 'updated' });
      } else {
        const item = await this.repo.save({
          destination_id: dto.destination_id,
          activity_id: dto.activity_id,
          ticket_id: dto.ticket_id || null,
          age_group: dto.age_group,
          currency_id: dto.currency_id,
          default_price: dto.default_price ?? null,
          season_1_price: dto.season_1_price ?? null,
          season_2_price: dto.season_2_price ?? null,
          season_3_price: dto.season_3_price ?? null,
          season_4_price: dto.season_4_price ?? null,
          season_5_price: dto.season_5_price ?? null,
        });
        results.push({ id: item.id, action: 'created' });
      }
    }
    return { results, message: `${results.length} pricing entries saved` };
  }

  async update(id: string, dto: UpdateActivityPricingDto) {
    const item = await this.repo.findById(id);
    if (!item) throw new NotFoundException(MSG.NOT_FOUND);

    const updateData: any = {};
    for (const field of ['default_price', 'season_1_price', 'season_2_price', 'season_3_price', 'season_4_price', 'season_5_price']) {
      if ((dto as any)[field] !== undefined) updateData[field] = (dto as any)[field];
    }

    await this.repo.update(id, updateData);
    return { id, message: MSG.UPDATED };
  }

  async remove(id: string) {
    const item = await this.repo.findById(id);
    if (!item) throw new NotFoundException(MSG.NOT_FOUND);

    // Hard delete pricing record
    await (this.repo as any).repo.delete(id);
    return { message: MSG.DELETED };
  }

  async removeByActivity(activityId: string) {
    const tenantId = (this.repo as any).getTenantId();
    // Hard delete all pricing for this activity (including soft-deleted)
    const result = await (this.repo as any).repo.delete({
      activity_id: activityId,
      tenant_id: tenantId,
    });
    return { message: `${result.affected || 0} pricing entries deleted` };
  }
}
