import {
  Injectable,
  Logger,
  NotFoundException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
import { CrmPrismaService } from '../prisma/crm-prisma.service';
import { RedisService } from '../redis/redis.service';
import {
  EnrichmentResponse,
  EnrichmentSuggestion,
} from './dto/enrich-response.dto';
import {
  NorthDataSettings,
  UpdateNorthDataSettingsDto,
} from './dto/enrichment-settings.dto';

const NORTH_DATA_KEY = (tenantId: string) =>
  `crm:${tenantId}:integrations:north_data`;

@Injectable()
export class EnrichmentService {
  private readonly logger = new Logger(EnrichmentService.name);

  constructor(
    private readonly prisma: CrmPrismaService,
    private readonly redis: RedisService,
    private readonly config: ConfigService,
    private readonly httpService: HttpService,
  ) {}

  // --------------------------------------------------------
  // Unternehmen anreichern (Suggestion-Only)
  // --------------------------------------------------------

  async enrichCompany(
    tenantId: string,
    companyId: string,
  ): Promise<EnrichmentResponse> {
    const company = await this.prisma.company.findFirst({
      where: { id: companyId, tenantId },
    });
    if (!company) {
      throw new NotFoundException('Unternehmen nicht gefunden');
    }

    const warnings: string[] = [];
    const sources: string[] = [];
    const suggestions: Record<string, EnrichmentSuggestion> = {};

    const northDataSettings = await this.getNorthDataSettings(tenantId);

    // Parallele Abfragen
    const [registerResult, northDataResult] = await Promise.allSettled([
      this.queryUnternehmensregister(company.name, company.city ?? undefined),
      northDataSettings.enabled && northDataSettings.apiKey
        ? this.queryNorthData(company.name, northDataSettings.apiKey)
        : Promise.resolve(null),
    ]);

    // Unternehmensregister.de Ergebnisse verarbeiten
    if (registerResult.status === 'fulfilled' && registerResult.value) {
      sources.push('unternehmensregister.de');
      const data = registerResult.value;

      this.addSuggestion(suggestions, 'tradeRegisterNumber', company.tradeRegisterNumber, data.registerNumber, 'unternehmensregister.de');
      this.addSuggestion(suggestions, 'registerCourt', company.registerCourt, data.registerCourt, 'unternehmensregister.de');
      this.addSuggestion(suggestions, 'street', company.street, data.street, 'unternehmensregister.de');
      this.addSuggestion(suggestions, 'zip', company.zip, data.zip, 'unternehmensregister.de');
      this.addSuggestion(suggestions, 'city', company.city, data.city, 'unternehmensregister.de');
    } else if (registerResult.status === 'rejected') {
      warnings.push(`Unternehmensregister: ${String(registerResult.reason)}`);
    }

    // North Data Ergebnisse verarbeiten
    if (northDataResult.status === 'fulfilled' && northDataResult.value) {
      sources.push('northdata.de');
      const data = northDataResult.value;

      this.addSuggestion(suggestions, 'name', company.name, data.name, 'northdata.de');
      this.addSuggestion(suggestions, 'vatId', company.vatId, data.vatId, 'northdata.de');
      this.addSuggestion(suggestions, 'website', company.website, data.website, 'northdata.de');
      this.addSuggestion(suggestions, 'phone', company.phone, data.phone, 'northdata.de');
      this.addSuggestion(suggestions, 'street', company.street, data.street, 'northdata.de');
      this.addSuggestion(suggestions, 'zip', company.zip, data.zip, 'northdata.de');
      this.addSuggestion(suggestions, 'city', company.city, data.city, 'northdata.de');
      this.addSuggestion(suggestions, 'industry', company.industry, data.industry, 'northdata.de');
    } else if (northDataResult.status === 'rejected' && northDataSettings.enabled) {
      warnings.push(`North Data: ${String(northDataResult.reason)}`);
    } else if (!northDataSettings.enabled) {
      warnings.push('North Data Integration ist nicht aktiviert.');
    }

    if (sources.length === 0) {
      warnings.push('Keine Datenquelle konnte abgefragt werden.');
    }

    return {
      companyId,
      companyName: company.name,
      sources,
      suggestions,
      enrichedAt: new Date().toISOString(),
      warnings,
    };
  }

  // --------------------------------------------------------
  // Unternehmensregister.de Abfrage (kostenfrei)
  // --------------------------------------------------------

  private async queryUnternehmensregister(
    companyName: string,
    city?: string,
  ): Promise<{
    registerNumber: string | null;
    registerCourt: string | null;
    street: string | null;
    zip: string | null;
    city: string | null;
  } | null> {
    try {
      const searchUrl = 'https://www.unternehmensregister.de/trxweb/api/search';

      const response = await firstValueFrom(
        this.httpService.get(searchUrl, {
          params: {
            keyword: companyName,
            ...(city ? { location: city } : {}),
          },
          timeout: 10000,
        }),
      );

      const data = response.data;

      if (data && typeof data === 'object') {
        return {
          registerNumber: data.registerNumber ?? null,
          registerCourt: data.registerCourt ?? null,
          street: data.street ?? null,
          zip: data.zip ?? null,
          city: data.city ?? null,
        };
      }

      return null;
    } catch (err) {
      this.logger.warn(
        `Unternehmensregister-Abfrage fehlgeschlagen fuer "${companyName}": ${err instanceof Error ? err.message : String(err)}`,
      );
      throw new Error('Unternehmensregister nicht erreichbar');
    }
  }

  // --------------------------------------------------------
  // North Data API Abfrage (kostenpflichtig)
  // --------------------------------------------------------

  private async queryNorthData(
    companyName: string,
    apiKey: string,
  ): Promise<{
    name: string | null;
    vatId: string | null;
    website: string | null;
    phone: string | null;
    street: string | null;
    zip: string | null;
    city: string | null;
    industry: string | null;
  } | null> {
    try {
      const baseUrl = this.config.get<string>(
        'NORTH_DATA_API_URL',
        'https://www.northdata.de/_api',
      );

      const response = await firstValueFrom(
        this.httpService.get(`${baseUrl}/company/v1/company`, {
          params: {
            name: companyName,
            address: 'DE',
          },
          headers: {
            'X-Api-Key': apiKey,
          },
          timeout: 15000,
        }),
      );

      const data = response.data;

      if (data && typeof data === 'object') {
        return {
          name: data.name?.current ?? null,
          vatId: data.vatId ?? null,
          website: data.website ?? null,
          phone: data.phone ?? null,
          street: data.address?.street ?? null,
          zip: data.address?.postalCode ?? null,
          city: data.address?.city ?? null,
          industry: data.industry?.description ?? null,
        };
      }

      return null;
    } catch (err) {
      this.logger.warn(
        `North Data Abfrage fehlgeschlagen fuer "${companyName}": ${err instanceof Error ? err.message : String(err)}`,
      );
      throw new Error('North Data API nicht erreichbar');
    }
  }

  // --------------------------------------------------------
  // Helfer: Suggestion hinzufuegen (nur wenn suggested != current)
  // --------------------------------------------------------

  private addSuggestion(
    suggestions: Record<string, EnrichmentSuggestion>,
    field: string,
    current: string | null | undefined,
    suggested: string | null | undefined,
    source: string,
  ): void {
    if (!suggested) return;

    const currentVal = current ?? null;
    const suggestedVal = suggested;

    // Nur hinzufuegen wenn current leer oder verschieden
    if (currentVal !== suggestedVal) {
      // Erste Quelle gewinnt bei Duplikaten
      if (!suggestions[field]) {
        suggestions[field] = {
          current: currentVal,
          suggested: suggestedVal,
          source,
        };
      }
    }
  }

  // --------------------------------------------------------
  // North Data Settings (Redis)
  // --------------------------------------------------------

  async getNorthDataSettings(tenantId: string): Promise<NorthDataSettings> {
    const key = NORTH_DATA_KEY(tenantId);
    const raw = await this.redis.get(key);

    if (!raw) {
      const envKey = this.config.get<string>('NORTH_DATA_API_KEY');
      return {
        apiKey: envKey ?? null,
        enabled: !!envKey,
      };
    }

    return JSON.parse(raw) as NorthDataSettings;
  }

  async updateNorthDataSettings(
    tenantId: string,
    dto: UpdateNorthDataSettingsDto,
  ): Promise<NorthDataSettings> {
    const current = await this.getNorthDataSettings(tenantId);

    const updated: NorthDataSettings = {
      apiKey: dto.apiKey !== undefined ? dto.apiKey : current.apiKey,
      enabled: dto.enabled !== undefined ? dto.enabled : current.enabled,
    };

    const key = NORTH_DATA_KEY(tenantId);
    await this.redis.set(key, JSON.stringify(updated));

    return updated;
  }

  // --------------------------------------------------------
  // Health Check
  // --------------------------------------------------------

  async isHealthy(): Promise<'up' | 'down' | 'unconfigured'> {
    const envKey = this.config.get<string>('NORTH_DATA_API_KEY');
    if (!envKey) return 'unconfigured';

    try {
      const baseUrl = this.config.get<string>(
        'NORTH_DATA_API_URL',
        'https://www.northdata.de/_api',
      );
      await firstValueFrom(
        this.httpService.get(`${baseUrl}/health`, {
          headers: { 'X-Api-Key': envKey },
          timeout: 5000,
        }),
      );
      return 'up';
    } catch {
      return 'down';
    }
  }
}
