/**
 * State Projector - Token-budgetierte Projektion des SDK-State
 *
 * Extrahiert aus dem vollen SDKState (der ~50k Tokens betragen kann) nur die
 * relevanten Slices fuer den jeweiligen Agent-Modus.
 *
 * Token-Budgets:
 * - Draft:    ~1500 Tokens
 * - Ask:      ~600 Tokens
 * - Validate: ~2000 Tokens
 */

import type { SDKState, CompanyProfile } from '../types'
import type {
  ComplianceScopeState,
  ScopeDecision,
  ScopeDocumentType,
  ScopeGap,
  RequiredDocument,
  RiskFlag,
  DOCUMENT_SCOPE_MATRIX,
  DocumentDepthRequirement,
} from '../compliance-scope-types'
import { DOCUMENT_SCOPE_MATRIX as DOC_MATRIX, DOCUMENT_TYPE_LABELS } from '../compliance-scope-types'
import type {
  DraftContext,
  GapContext,
  ValidationContext,
} from './types'

// ============================================================================
// State Projector
// ============================================================================

export class StateProjector {

  /**
   * Projiziert den SDKState fuer Draft-Operationen.
   * Fokus: Scope-Decision, Company-Profile, Dokument-spezifische Constraints.
   *
   * ~1500 Tokens
   */
  projectForDraft(
    state: SDKState,
    documentType: ScopeDocumentType
  ): DraftContext {
    const decision = state.complianceScope?.decision ?? null
    const level = decision?.determinedLevel ?? 'L1'
    const depthReq = DOC_MATRIX[documentType]?.[level] ?? {
      required: false,
      depth: 'Basis',
      detailItems: [],
      estimatedEffort: 'N/A',
    }

    return {
      decisions: {
        level,
        scores: decision?.scores ?? {
          risk_score: 0,
          complexity_score: 0,
          assurance_need: 0,
          composite_score: 0,
        },
        hardTriggers: (decision?.triggeredHardTriggers ?? []).map(t => ({
          id: t.rule.id,
          label: t.rule.label,
          legalReference: t.rule.legalReference,
        })),
        requiredDocuments: (decision?.requiredDocuments ?? [])
          .filter(d => d.required)
          .map(d => ({
            documentType: d.documentType,
            depth: d.depth,
            detailItems: d.detailItems,
          })),
      },
      companyProfile: this.projectCompanyProfile(state.companyProfile),
      constraints: {
        depthRequirements: depthReq,
        riskFlags: (decision?.riskFlags ?? []).map(f => ({
          severity: f.severity,
          title: f.title,
          recommendation: f.recommendation,
        })),
        boundaries: this.deriveBoundaries(decision, documentType),
      },
      existingDocumentData: this.extractExistingDocumentData(state, documentType),
    }
  }

  /**
   * Projiziert den SDKState fuer Ask-Operationen.
   * Fokus: Luecken, unbeantwortete Fragen, fehlende Dokumente.
   *
   * ~600 Tokens
   */
  projectForAsk(state: SDKState): GapContext {
    const decision = state.complianceScope?.decision ?? null

    // Fehlende Pflichtdokumente ermitteln
    const requiredDocs = (decision?.requiredDocuments ?? []).filter(d => d.required)
    const existingDocTypes = this.getExistingDocumentTypes(state)
    const missingDocuments = requiredDocs
      .filter(d => !existingDocTypes.includes(d.documentType))
      .map(d => ({
        documentType: d.documentType,
        label: DOCUMENT_TYPE_LABELS[d.documentType] ?? d.documentType,
        depth: d.depth,
        estimatedEffort: d.estimatedEffort,
      }))

    // Gaps aus der Scope-Decision
    const gaps = (decision?.gaps ?? []).map(g => ({
      id: g.id,
      severity: g.severity,
      title: g.title,
      description: g.description,
      relatedDocuments: g.relatedDocuments,
    }))

    // Unbeantwortete Fragen (aus dem Scope-Profiling)
    const answers = state.complianceScope?.answers ?? []
    const answeredIds = new Set(answers.map(a => a.questionId))

    return {
      unansweredQuestions: [], // Populated dynamically from question catalog
      gaps,
      missingDocuments,
    }
  }

  /**
   * Projiziert den SDKState fuer Validate-Operationen.
   * Fokus: Cross-Dokument-Konsistenz, Scope-Compliance.
   *
   * ~2000 Tokens
   */
  projectForValidate(
    state: SDKState,
    documentTypes: ScopeDocumentType[]
  ): ValidationContext {
    const decision = state.complianceScope?.decision ?? null
    const level = decision?.determinedLevel ?? 'L1'

    // Dokument-Zusammenfassungen sammeln
    const documents = documentTypes.map(type => ({
      type,
      contentSummary: this.summarizeDocument(state, type),
      structuredData: this.extractExistingDocumentData(state, type),
    }))

    // Cross-Referenzen extrahieren
    const crossReferences = {
      vvtCategories: (state.vvt ?? []).map(v =>
        typeof v === 'object' && v !== null && 'name' in v ? String((v as Record<string, unknown>).name) : ''
      ).filter(Boolean),
      dsfaRisks: state.dsfa
        ? ['DSFA vorhanden']
        : [],
      tomControls: (state.toms ?? []).map(t =>
        typeof t === 'object' && t !== null && 'name' in t ? String((t as Record<string, unknown>).name) : ''
      ).filter(Boolean),
      retentionCategories: (state.retentionPolicies ?? []).map(p =>
        typeof p === 'object' && p !== null && 'name' in p ? String((p as Record<string, unknown>).name) : ''
      ).filter(Boolean),
    }

    // Depth-Requirements fuer alle angefragten Typen
    const depthRequirements: Record<string, DocumentDepthRequirement> = {}
    for (const type of documentTypes) {
      depthRequirements[type] = DOC_MATRIX[type]?.[level] ?? {
        required: false,
        depth: 'Basis',
        detailItems: [],
        estimatedEffort: 'N/A',
      }
    }

    return {
      documents,
      crossReferences,
      scopeLevel: level,
      depthRequirements: depthRequirements as Record<ScopeDocumentType, DocumentDepthRequirement>,
    }
  }

  // ==========================================================================
  // Private Helpers
  // ==========================================================================

  private projectCompanyProfile(
    profile: CompanyProfile | null
  ): DraftContext['companyProfile'] {
    if (!profile) {
      return {
        name: 'Unbekannt',
        industry: 'Unbekannt',
        employeeCount: 0,
        businessModel: 'Unbekannt',
        isPublicSector: false,
      }
    }

    return {
      name: profile.companyName ?? profile.name ?? 'Unbekannt',
      industry: profile.industry ?? 'Unbekannt',
      employeeCount: typeof profile.employeeCount === 'number'
        ? profile.employeeCount
        : parseInt(String(profile.employeeCount ?? '0'), 10) || 0,
      businessModel: profile.businessModel ?? 'Unbekannt',
      isPublicSector: profile.isPublicSector ?? false,
      ...(profile.dataProtectionOfficer ? {
        dataProtectionOfficer: {
          name: profile.dataProtectionOfficer.name ?? '',
          email: profile.dataProtectionOfficer.email ?? '',
        },
      } : {}),
    }
  }

  /**
   * Leitet Grenzen (Boundaries) ab, die der Agent nicht ueberschreiten darf.
   */
  private deriveBoundaries(
    decision: ScopeDecision | null,
    documentType: ScopeDocumentType
  ): string[] {
    const boundaries: string[] = []
    const level = decision?.determinedLevel ?? 'L1'

    // Grundregel: Scope-Engine ist autoritativ
    boundaries.push(
      `Maximale Dokumenttiefe: ${level} (${DOC_MATRIX[documentType]?.[level]?.depth ?? 'Basis'})`
    )

    // DSFA-Boundary
    if (documentType === 'dsfa') {
      const dsfaRequired = decision?.triggeredHardTriggers?.some(
        t => t.rule.dsfaRequired
      ) ?? false
      if (!dsfaRequired && level !== 'L4') {
        boundaries.push('DSFA ist laut Scope-Engine NICHT erforderlich. Nur auf expliziten Wunsch erstellen.')
      }
    }

    // Dokument nicht in requiredDocuments?
    const isRequired = decision?.requiredDocuments?.some(
      d => d.documentType === documentType && d.required
    ) ?? false
    if (!isRequired) {
      boundaries.push(
        `Dokument "${DOCUMENT_TYPE_LABELS[documentType] ?? documentType}" ist auf Level ${level} nicht als Pflicht eingestuft.`
      )
    }

    return boundaries
  }

  /**
   * Extrahiert bereits vorhandene Dokumentdaten aus dem SDK-State.
   */
  private extractExistingDocumentData(
    state: SDKState,
    documentType: ScopeDocumentType
  ): Record<string, unknown> | undefined {
    switch (documentType) {
      case 'vvt':
        return state.vvt?.length ? { entries: state.vvt.slice(0, 5), totalCount: state.vvt.length } : undefined
      case 'tom':
        return state.toms?.length ? { entries: state.toms.slice(0, 5), totalCount: state.toms.length } : undefined
      case 'lf':
        return state.retentionPolicies?.length
          ? { entries: state.retentionPolicies.slice(0, 5), totalCount: state.retentionPolicies.length }
          : undefined
      case 'dsfa':
        return state.dsfa ? { assessment: state.dsfa } : undefined
      case 'dsi':
        return state.documents?.length
          ? { entries: state.documents.slice(0, 3), totalCount: state.documents.length }
          : undefined
      case 'einwilligung':
        return state.consents?.length
          ? { entries: state.consents.slice(0, 5), totalCount: state.consents.length }
          : undefined
      default:
        return undefined
    }
  }

  /**
   * Ermittelt welche Dokumenttypen bereits im State vorhanden sind.
   */
  private getExistingDocumentTypes(state: SDKState): ScopeDocumentType[] {
    const types: ScopeDocumentType[] = []
    if (state.vvt?.length) types.push('vvt')
    if (state.toms?.length) types.push('tom')
    if (state.retentionPolicies?.length) types.push('lf')
    if (state.dsfa) types.push('dsfa')
    if (state.documents?.length) types.push('dsi')
    if (state.consents?.length) types.push('einwilligung')
    if (state.cookieBanner) types.push('einwilligung')
    return types
  }

  /**
   * Erstellt eine kurze Zusammenfassung eines Dokuments fuer Validierung.
   */
  private summarizeDocument(
    state: SDKState,
    documentType: ScopeDocumentType
  ): string {
    switch (documentType) {
      case 'vvt':
        return state.vvt?.length
          ? `${state.vvt.length} Verarbeitungstaetigkeiten erfasst`
          : 'Keine VVT-Eintraege vorhanden'
      case 'tom':
        return state.toms?.length
          ? `${state.toms.length} TOM-Massnahmen definiert`
          : 'Keine TOM-Massnahmen vorhanden'
      case 'lf':
        return state.retentionPolicies?.length
          ? `${state.retentionPolicies.length} Loeschfristen definiert`
          : 'Keine Loeschfristen vorhanden'
      case 'dsfa':
        return state.dsfa
          ? 'DSFA vorhanden'
          : 'Keine DSFA vorhanden'
      default:
        return `Dokument ${DOCUMENT_TYPE_LABELS[documentType] ?? documentType}`
    }
  }
}

/** Singleton-Instanz */
export const stateProjector = new StateProjector()
