import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import {
  Entity, PrimaryGeneratedColumn, Column,
  CreateDateColumn, UpdateDateColumn,
} from 'typeorm';
import {
  Injectable, NotFoundException, OnModuleInit,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, DataSource } from 'typeorm';
import {
  Controller, Get, Put, Body, Param, UseGuards, Request,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import {
  IsOptional, IsString, IsBoolean, IsNumber,
  IsEmail, IsUrl, MinLength,
} from 'class-validator';
import { ApiPropertyOptional } from '@nestjs/swagger';

// ============================================================
// ENTITY (reusa a do AuthModule — mantida aqui para TypeORM)
// ============================================================
@Entity('tenants')
export class TenantEntity {
  @PrimaryGeneratedColumn('uuid') id: string;
  @Column({ length: 150 }) name: string;
  @Column({ length: 14, unique: true }) document: string;
  @Column({ length: 80 }) email: string;
  @Column({ nullable: true }) phone: string;
  @Column({ name: 'municipal_inscription', nullable: true }) municipalInscription: string;
  @Column({ name: 'ibge_code', nullable: true }) ibgeCode: string;
  @Column({ nullable: true }) uf: string;
  @Column({ name: 'tax_regime', type: 'smallint', default: 1 }) taxRegime: number;
  @Column({ name: 'simple_national', default: false }) simpleNational: boolean;
  @Column({ name: 'fiscal_incentive', default: false }) fiscalIncentive: boolean;
  @Column({ name: 'autentique_token', nullable: true }) autentiqueToken: string;
  @Column({ name: 'nfse_url', nullable: true }) nfseUrl: string;
  @Column({ name: 'nfse_certificate', type: 'text', nullable: true }) nfseCertificate: string;
  @Column({ name: 'nfse_certificate_pass', nullable: true }) nfseCertificatePass: string;
  @Column({ name: 'proposal_template', type: 'text', nullable: true }) proposalTemplate: string; // JSON with intro, paymentConditions, terms, footer, signatureBlock
  @Column({ name: 'logo_url', type: 'text', nullable: true }) logoUrl: string;
  @Column({ name: 'smtp_host', nullable: true }) smtpHost: string;
  @Column({ name: 'smtp_port', type: 'smallint', default: 587 }) smtpPort: number;
  @Column({ name: 'smtp_user', nullable: true }) smtpUser: string;
  @Column({ name: 'smtp_pass', nullable: true }) smtpPass: string;
  @Column({ name: 'smtp_from', nullable: true }) smtpFrom: string;
  @Column({ name: 'smtp_secure', default: false }) smtpSecure: boolean;
  @Column({ default: 'trial' }) plan: string;
  @Column({ default: 'active' }) status: string;
  // ── v.api ──────────────────────────────────────────────────────────────────
  @Column({ name: 'letterhead_pdf', type: 'text', nullable: true }) letterheadPdf: string;
  @Column({ name: 'vapi_api_key', nullable: true }) vapiApiKey: string;
  @Column({ name: 'vapi_pix_key', nullable: true }) vapiPixKey: string;
  @CreateDateColumn({ name: 'created_at' }) createdAt: Date;
  @UpdateDateColumn({ name: 'updated_at' }) updatedAt: Date;
}

// ============================================================
// DTO
// ============================================================
export class UpdateTenantDto {
  @ApiPropertyOptional() @IsOptional() @IsString() name?: string;
  @ApiPropertyOptional() @IsOptional() @IsEmail() email?: string;
  @ApiPropertyOptional() @IsOptional() @IsString() phone?: string;
  @ApiPropertyOptional({ description: 'Inscrição municipal' })
  @IsOptional() @IsString() municipalInscription?: string;
  @ApiPropertyOptional({ description: 'Código IBGE do município' })
  @IsOptional() @IsString() ibgeCode?: string;
  @ApiPropertyOptional() @IsOptional() @IsString() uf?: string;
  @ApiPropertyOptional({ enum: [1,2,3,4,5,6] })
  @IsOptional() @IsNumber() taxRegime?: number;
  @ApiPropertyOptional() @IsOptional() @IsBoolean() simpleNational?: boolean;
  @ApiPropertyOptional() @IsOptional() @IsBoolean() fiscalIncentive?: boolean;
  @ApiPropertyOptional({ description: 'Token da Autentique' })
  @IsOptional() @IsString() autentiqueToken?: string;
  @ApiPropertyOptional({ description: 'URL do WebService NFS-e da prefeitura' })
  @IsOptional() @IsString() nfseUrl?: string;
  @ApiPropertyOptional({ description: 'Certificado A1 em base64' })
  @IsOptional() @IsString() nfseCertificate?: string;
  @ApiPropertyOptional() @IsOptional() @IsString() nfseCertificatePass?: string;
  @ApiPropertyOptional({ description: 'JSON serializado com campos do modelo de proposta' })
  @IsOptional() @IsString() proposalTemplate?: string;
  @ApiPropertyOptional({ description: 'Logo da empresa em base64 (data URL)' })
  @IsOptional() @IsString() logoUrl?: string;
  @ApiPropertyOptional() @IsOptional() @IsString() smtpHost?: string;
  @ApiPropertyOptional() @IsOptional() @IsNumber() smtpPort?: number;
  @ApiPropertyOptional() @IsOptional() @IsString() smtpUser?: string;
  @ApiPropertyOptional() @IsOptional() @IsString() smtpPass?: string;
  @ApiPropertyOptional() @IsOptional() @IsString() smtpFrom?: string;
  @ApiPropertyOptional() @IsOptional() @IsBoolean() smtpSecure?: boolean;
  @ApiPropertyOptional({ description: 'API Key do v.api (formato: vapi_<64hex>)' })
  @IsOptional() @IsString() vapiApiKey?: string;
  @ApiPropertyOptional({ description: 'Chave PIX do recebedor (CPF, CNPJ, e-mail, telefone ou chave aleatória)' })
  @IsOptional() @IsString() vapiPixKey?: string;
  @ApiPropertyOptional({ description: 'PDF do timbre em base64 (para gerar contratos)' })
  @IsOptional() @IsString() letterheadPdf?: string;
}

// ============================================================
// SERVICE
// ============================================================
@Injectable()
export class TenantsService implements OnModuleInit {
  constructor(
    @InjectRepository(TenantEntity)
    private readonly tenantRepo: Repository<TenantEntity>,
    private readonly dataSource: DataSource,
  ) {}

  async onModuleInit() {
    // Cada statement separado — multi-statement em uma única query() pode ser
    // rejeitado pelo extended protocol do pg e o catch silencia o erro.
    const migrations = [
      // ── Estrutura base ──────────────────────────────────────────────────
      `CREATE TABLE IF NOT EXISTS tenant_sequences (
         tenant_id  UUID        NOT NULL,
         entity     VARCHAR(50) NOT NULL,
         last_value BIGINT      NOT NULL DEFAULT 0,
         PRIMARY KEY (tenant_id, entity)
       )`,
      // ── Colunas adicionadas ao longo do tempo (idempotente) ─────────────
      `ALTER TABLE products ADD COLUMN IF NOT EXISTS contract_template TEXT`,
      `ALTER TABLE tenants  ADD COLUMN IF NOT EXISTS letterhead_pdf TEXT`,
      // invoices — colunas pós-schema inicial
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS charge_id          UUID`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS contract_id        UUID`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS iss_aliquota       NUMERIC(4,2)`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS iss_retained       BOOLEAN NOT NULL DEFAULT false`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS iss_amount         NUMERIC(15,2)`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS nfse_issued_at     TIMESTAMPTZ`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS cancel_code        SMALLINT`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS cancel_reason      VARCHAR(255)`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS cancelled_at       TIMESTAMPTZ`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS cancel_xml         TEXT`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS consulta_fail_count SMALLINT NOT NULL DEFAULT 0`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS queued_at          TIMESTAMPTZ`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS abrasf_protocol    VARCHAR(255)`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS email_sent_at      TIMESTAMPTZ`,
      `ALTER TABLE invoices ADD COLUMN IF NOT EXISTS cnae_code          VARCHAR(15)`,
      // nfse_verify_code: aumenta para 100 para acomodar chaves nacionais longas
      `ALTER TABLE invoices ALTER COLUMN nfse_verify_code TYPE VARCHAR(100)`,
    ];
    for (const sql of migrations) {
      await this.dataSource.query(sql)
        .catch((e: Error) => console.warn('Migration warning:', e.message));
    }
  }

  async findOne(id: string): Promise<TenantEntity> {
    const tenant = await this.tenantRepo.findOneBy({ id });
    if (!tenant) throw new NotFoundException('Tenant não encontrado');
    return tenant;
  }

  async update(id: string, dto: UpdateTenantDto): Promise<TenantEntity> {
    const tenant = await this.findOne(id);
    Object.assign(tenant, dto);
    return this.tenantRepo.save(tenant);
  }
}

// ============================================================
// CONTROLLER
// ============================================================
@ApiTags('Tenant')
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'))
@Controller('tenant')
export class TenantsController {
  constructor(private readonly tenantsService: TenantsService) {}

  @Get()
  @ApiOperation({ summary: 'Dados da empresa autenticada' })
  findOne(@Request() req: any) {
    return this.tenantsService.findOne(req.user.tenantId);
  }

  @Put()
  @ApiOperation({ summary: 'Atualizar dados da empresa (config fiscal + Autentique)' })
  update(@Request() req: any, @Body() dto: UpdateTenantDto) {
    return this.tenantsService.update(req.user.tenantId, dto);
  }
}

// ============================================================
// MODULE
// ============================================================
@Module({
  imports: [TypeOrmModule.forFeature([TenantEntity])],
  controllers: [TenantsController],
  providers: [TenantsService],
  exports: [TenantsService],
})
export class TenantsModule {}
