import {
  Injectable,
  ConflictException,
  NotFoundException,
} from '@nestjs/common';
import { TripSourceRepository } from './repositories/trip-source.repository';
import { CreateTripSourceDto, UpdateTripSourceDto } from './dto';
import { serviceMessages } from '../../common/constants/messages';

const MSG = serviceMessages('Trip source');

@Injectable()
export class TripSourceService {
  constructor(private readonly repo: TripSourceRepository) {}

  async findAll(query?: { page?: number; limit?: number; search?: string }, filters?: { sourceType?: string; status?: string }) {
    const where: any = {};
    if (filters?.sourceType) where.source_type = filters.sourceType;
    if (filters?.status) where.is_active = filters.status === 'active';

    return this.repo.findPaginated({
      page: query?.page,
      limit: query?.limit,
      search: query?.search,
      searchColumns: ['name', 'short_name', 'contact_name', 'city', 'country'],
      relations: [],
      order: { name: 'ASC' },
      where,
    });
  }

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

  async create(dto: CreateTripSourceDto) {
    const existing = await this.repo.findByShortName(dto.short_name);
    if (existing) throw new ConflictException(MSG.ALREADY_EXISTS('short name'));

    const item = await this.repo.save({
      source_type: dto.source_type,
      name: dto.name,
      short_name: dto.short_name,
      contact_name: dto.contact_name,
      contact_email: dto.contact_email || null,
      contact_phone_code: dto.contact_phone_code || null,
      contact_phone: dto.contact_phone || null,
      city: dto.city || null,
      state: dto.state || null,
      country: dto.country || null,
      pin_code: dto.pin_code || null,
      street_address: dto.street_address || null,
      locality: dto.locality || null,
      landmark: dto.landmark || null,
      billing_name: dto.billing_name || null,
      billing_details: dto.billing_details || null,
      is_active: dto.is_active ?? true,
    });

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

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

    if (dto.short_name && dto.short_name !== item.short_name) {
      const existing = await this.repo.findByShortName(dto.short_name);
      if (existing) throw new ConflictException(MSG.ALREADY_EXISTS('short name'));
    }

    const updateData: any = {};
    const fields = [
      'source_type', 'name', 'short_name', 'contact_name', 'contact_email',
      'contact_phone_code', 'contact_phone', 'city', 'state', 'country',
      'pin_code', 'street_address', 'locality', 'landmark',
      'billing_name', 'billing_details', 'is_active',
    ];
    for (const field of fields) {
      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);

    await this.repo.softDelete(id);
    return { message: MSG.DELETED };
  }
}
