import {
  Injectable, ConflictException, NotFoundException, BadRequestException,
} from '@nestjs/common';
import { TaxTypeRepository } from './repositories/tax-type.repository';
import { CreateTaxTypeDto, UpdateTaxTypeDto } from './dto';
import { serviceMessages } from '../../common/constants/messages';

const MSG = serviceMessages('Tax type');

@Injectable()
export class TaxTypeService {
  constructor(private readonly repo: TaxTypeRepository) {}

  async findAll(query?: { page?: number; limit?: number; search?: string }) {
    return this.repo.findPaginated({
      page: query?.page,
      limit: query?.limit,
      search: query?.search,
      searchColumns: ['name', 'display_name'],
      relations: [],
      order: { name: 'ASC' },
    });
  }

  async findAllActive() {
    return this.repo.findAllActive();
  }

  async findAllForLookup() {
    return this.repo.find({
      where: { is_active: true } as any,
      select: ['id', 'name', 'default_value'],
      order: { name: 'ASC' } as any,
    });
  }

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

  async create(dto: CreateTaxTypeDto) {
    const existing = await this.repo.findByName(dto.name);
    if (existing) throw new ConflictException(MSG.ALREADY_EXISTS('name'));

    const item = await this.repo.save({
      name: dto.name,
      display_name: dto.display_name,
      default_value: dto.default_value ?? 0,
      is_active: dto.is_active !== undefined ? dto.is_active : true,
      is_system: false,
    });

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

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

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

    const updateData: any = {};
    if (dto.name !== undefined) updateData.name = dto.name;
    if (dto.display_name !== undefined) updateData.display_name = dto.display_name;
    if (dto.default_value !== undefined) updateData.default_value = dto.default_value;
    if (dto.is_active !== undefined) updateData.is_active = dto.is_active;

    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);
    if (item.is_system) throw new BadRequestException(MSG.CANNOT_DELETE_SYSTEM);

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