import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { OrdemServico } from './entities/ordem-servico.entity';
import { Avaliacao } from './entities/avaliacao.entity';
import { DocumentoVersao } from './entities/documento-versao.entity';
import * as fs from 'fs';
import * as path from 'path';

const UPLOAD_DIR = process.env.UPLOAD_DIR || '/opt/hefesto/uploads';

@Injectable()
export class OrdensServicoService {
  constructor(
    @InjectRepository(OrdemServico) private repo: Repository<OrdemServico>,
    @InjectRepository(Avaliacao) private avalRepo: Repository<Avaliacao>,
    @InjectRepository(DocumentoVersao) private docRepo: Repository<DocumentoVersao>,
  ) {
    if (!fs.existsSync(UPLOAD_DIR)) {
      fs.mkdirSync(UPLOAD_DIR, { recursive: true });
    }
  }

  findAll() { return this.repo.find({ order: { created_at: 'DESC' } }); }
  findOne(id: string) { return this.repo.findOne({ where: { id } }); }
  
  findByDemanda(demandaId: string) {
    return this.repo.find({ where: { demanda_id: demandaId }, order: { created_at: 'DESC' } });
  }

  async create(data: Partial<OrdemServico>) {
    // Auto-number
    const last = await this.repo.query('SELECT MAX(numero) as max FROM ordens_servico');
    const nextNum = (last[0]?.max || 0) + 1;
    return this.repo.save({ ...data, numero: nextNum, status: data.status || 'emitida' });
  }

  async update(id: string, data: Partial<OrdemServico>) {
    await this.repo.update(id, data);
    return this.findOne(id);
  }

  async remove(id: string) { await this.repo.delete(id); return { deleted: true }; }

  async iniciar(id: string) { await this.repo.update(id, { status: 'em_execucao', data_inicio: new Date().toISOString().split('T')[0] }); return this.findOne(id); }
  async concluir(id: string) { await this.repo.update(id, { status: 'concluida', data_conclusao: new Date().toISOString().split('T')[0] }); return this.findOne(id); }
  async cancelar(id: string) { await this.repo.update(id, { status: 'cancelada' }); return this.findOne(id); }
  async updateStatus(id: string, status: string) { await this.repo.update(id, { status }); return this.findOne(id); }

  createAvaliacao(data: Partial<Avaliacao>) { return this.avalRepo.save(data); }

  // Document versioning
  findDocumentos(osId: string) {
    return this.docRepo.find({ where: { ordem_servico_id: osId }, order: { versao: 'DESC' } });
  }

  async uploadDocumento(osId: string, file: Express.Multer.File, fornecedorId?: string) {
    const ext = path.extname(file.originalname);
    const filename = `os_${osId}_${Date.now()}${ext}`;
    const destPath = path.join(UPLOAD_DIR, filename);
    fs.writeFileSync(destPath, file.buffer);

    // Calculate next version
    const existing = await this.docRepo.find({ 
      where: { ordem_servico_id: osId, fornecedor_id: fornecedorId || undefined } as any,
      order: { versao: 'DESC' } 
    });
    const nextVersion = existing.length > 0 ? existing[0].versao + 1 : 1;

    const doc = await this.docRepo.save({
      ordem_servico_id: osId,
      fornecedor_id: fornecedorId,
      nome_arquivo: file.originalname,
      caminho: filename,
      tamanho: file.size,
      versao: nextVersion,
    });

    return doc;
  }

  async downloadDocumento(id: string) {
    const doc = await this.docRepo.findOne({ where: { id } });
    if (!doc) throw new Error('Documento não encontrado');
    return { doc, filePath: path.join(UPLOAD_DIR, doc.caminho) };
  }

  // Check if fornecedor has OS
  async fornecedorHasOS(fornecedorId: string): Promise<boolean> {
    const count = await this.repo.count({ where: { fornecedor_id: fornecedorId } });
    return count > 0;
  }
}
