import { dimensionService } from '@/services/dimensionService';
import { ENVELOPE_DIMENSIONS, REQUIRED_ENVELOPE_KEYS, MANUFACTURER_SPEC_FIELDS, JOINT_CATEGORIES, MOVEMENT_POSITIONS, CAD_BLOCKING_SOURCES } from '@/services/dimensionDefinitions';

const verifiedSource = (d) => ['Manufacturer Verified Specification','Workshop Physical Measurement','3D Scan Measurement'].includes(d.source) && d.verification_status !== 'Conflict detected' && d.verification_status !== 'Superseded' && d.verification_status !== 'Unknown';

export const dimensionAnalysis = {
  async completeness(component) {
    const [dims, specs, stations, access, keepouts, movements] = await Promise.all([
      dimensionService.dimensions(component.uuid),
      dimensionService.specs(component.uuid),
      dimensionService.stations(component.uuid),
      dimensionService.accessPoints(component.uuid),
      dimensionService.keepOutZones(component.uuid),
      dimensionService.movementPositions(component.uuid),
    ]);
    const specKeys = MANUFACTURER_SPEC_FIELDS.map(f => f[0]);
    const specsFound = specs.filter(s => specKeys.some(k => s[k] != null && s[k] !== '' && s[k] !== 'Not Published'));
    const specsMissing = specKeys.filter(k => !specs.some(s => s[k] != null && s[k] !== '' && s[k] !== 'Not Published'));
    const envDims = dims.filter(d => d.category === 'External envelope' || ENVELOPE_DIMENSIONS.some(e => e[0] === d.dimension_key));
    const envComplete = REQUIRED_ENVELOPE_KEYS.filter(k => envDims.some(d => d.dimension_key === k && verifiedSource(d)));
    const envMissing = REQUIRED_ENVELOPE_KEYS.filter(k => !envComplete.includes(k));
    const isJoint = JOINT_CATEGORIES.includes(component.category);
    const requiredPositions = isJoint ? MOVEMENT_POSITIONS.map(p => p[0]) : [];
    const positionsDone = movements.filter(m => requiredPositions.includes(m.position_name)).map(m => m.position_name);
    const positionsMissing = requiredPositions.filter(p => !positionsDone.includes(p));
    const photos = [...dims, ...stations, ...access, ...movements].filter(x => x.photo_url || x.photograph_url || x.scan_url);
    const sourcesVerified = specs.filter(s => s.is_official_source && s.verified_by);
    const checks = [
      { label: 'Manufacturer specifications found', done: specsFound.length, total: specKeys.length },
      { label: 'Workshop measurements complete', done: envComplete.length, total: REQUIRED_ENVELOPE_KEYS.length },
      { label: 'Measurement stations', done: stations.length, total: 1 },
      { label: 'Access zones', done: access.length, total: 1 },
      { label: 'Keep-out zones', done: keepouts.length, total: 1 },
      { label: 'Dynamic envelope positions', done: requiredPositions.length === 0 ? 1 : positionsDone.length, total: requiredPositions.length || 1 },
      { label: 'Photos', done: photos.length, total: 1 },
      { label: 'Source documents verified', done: sourcesVerified.length, total: 1 },
    ];
    const overall = Math.round(checks.reduce((s, c) => s + Math.min(c.done / c.total, 1), 0) / checks.length * 100);
    const blocking = [];
    if (!component.model) blocking.push('Exact model identification missing');
    if (specs.length === 0) blocking.push('Manufacturer specification source not recorded');
    if (envMissing.includes('overall_max_width')) blocking.push('Real maximum width not verified');
    if (envMissing.includes('overall_max_depth')) blocking.push('Real maximum depth not verified');
    if (envMissing.includes('overall_height')) blocking.push('Overall installed height not verified');
    if (envMissing.includes('proximal_connector_width')) blocking.push('Proximal connection envelope not verified');
    if (envMissing.includes('distal_connector_width')) blocking.push('Distal connection envelope not verified');
    if (access.length === 0) blocking.push('Access points not recorded');
    if (keepouts.length === 0) blocking.push('Keep-out zones not recorded');
    if (isJoint && positionsMissing.length > 0) blocking.push('Movement envelope incomplete');
    if (photos.length === 0) blocking.push('Required photos missing');
    const conflicts = await this.conflicts(component, dims);
    if (conflicts.length > 0) blocking.push(`${conflicts.length} unresolved dimension conflict(s)`);
    return { checks, overall, blocking, specsMissing, envMissing, positionsMissing, conflicts };
  },

  async conflicts(component, dims) {
    const conflicts = [];
    const byKey = {};
    dims.forEach(d => { if (!byKey[d.dimension_key]) byKey[d.dimension_key] = []; byKey[d.dimension_key].push(d); });
    Object.entries(byKey).forEach(([key, records]) => {
      const mfr = records.find(r => r.source === 'Manufacturer Verified Specification' && r.value_mm != null);
      const work = records.find(r => r.source === 'Workshop Physical Measurement' && r.value_mm != null);
      if (mfr && work && Math.abs(mfr.value_mm - work.value_mm) / Math.max(mfr.value_mm, 1) > 0.1)
        conflicts.push({ key, type: 'Manufacturer vs workshop mismatch', detail: `Manufacturer ${mfr.value_mm} mm vs workshop ${work.value_mm} mm` });
      const sorted = records.filter(r => r.value_mm != null).sort((a, b) => (a.date_entered || '').localeCompare(b.date_entered || ''));
      if (sorted.length >= 2) {
        const last = sorted[sorted.length - 1], prev = sorted[sorted.length - 2];
        if (prev.value_mm > 0 && Math.abs(last.value_mm - prev.value_mm) / prev.value_mm > 0.25)
          conflicts.push({ key, type: 'Significant change between measurements', detail: `Previous ${prev.value_mm} mm vs latest ${last.value_mm} mm` });
      }
      const dim = [...ENVELOPE_DIMENSIONS].find(e => e[0] === key);
      if (dim && dim[2] === 'mm') {
        const val = records[0];
        if (val?.value_mm != null && val.value_mm > 0 && val.value_mm < 15 && val.entered_unit === 'mm')
          conflicts.push({ key, type: 'Likely millimetre/centimetre error', detail: `Value ${val.value_mm} mm seems too small for ${dim[1]}` });
      }
    });
    const blockingDims = dims.filter(d => CAD_BLOCKING_SOURCES.includes(d.source) && d.verification_status !== 'Not applicable');
    if (blockingDims.length > 0)
      conflicts.push({ key: '_blocking', type: 'Non-verified sources present', detail: `${blockingDims.length} dimension(s) use sources that cannot satisfy CAD validation` });
    return conflicts;
  },

  async buildWorkflow(component) {
    const dims = await dimensionService.dimensions(component.uuid);
    const complete = await this.completeness(component);
    const tasks = [];
    for (const key of complete.envMissing) {
      const dim = ENVELOPE_DIMENSIONS.find(e => e[0] === key);
      if (dim) tasks.push({ key, name: dim[1], unit: dim[2], source: 'Workshop Physical Measurement', explanation: `Workshop measurement required — manufacturer spec does not provide this envelope value.` });
    }
    if (complete.specsMissing.length > 0)
      tasks.push({ key: '_spec_import', name: 'Import manufacturer specifications', unit: 'text', source: 'Manufacturer Verified Specification', explanation: `${complete.specsMissing.length} manufacturer spec values still missing.` });
    if (complete.positionsMissing.length > 0)
      tasks.push({ key: '_movement', name: 'Record movement envelope', unit: 'text', source: 'Workshop Physical Measurement', explanation: `${complete.positionsMissing.length} movement positions still required for this joint.` });
    if (complete.blocking.includes('Access points not recorded'))
      tasks.push({ key: '_access', name: 'Record access points', unit: 'text', source: 'Workshop Physical Measurement', explanation: 'No access zones recorded yet.' });
    if (complete.blocking.includes('Keep-out zones not recorded'))
      tasks.push({ key: '_keepout', name: 'Record keep-out zones', unit: 'text', source: 'Workshop Physical Measurement', explanation: 'No keep-out zones recorded yet.' });
    return tasks;
  },

  async exportData(component, format) {
    const [dims, specs, stations, access, keepouts, movements] = await Promise.all([
      dimensionService.dimensions(component.uuid), dimensionService.specs(component.uuid),
      dimensionService.stations(component.uuid), dimensionService.accessPoints(component.uuid),
      dimensionService.keepOutZones(component.uuid), dimensionService.movementPositions(component.uuid),
    ]);
    const data = { component, manufacturer_specs: specs, dimensions: dims, envelope_stations: stations, access_points: access, keep_out_zones: keepouts, movement_positions: movements };
    if (format === 'json') return JSON.stringify(data, null, 2);
    if (format === 'csv') {
      const rows = [['dimension_name','dimension_key','source','value_mm','text_value','unit','verification_status','entered_by','date_entered']];
      dims.forEach(d => rows.push([d.dimension_name, d.dimension_key, d.source, d.value_mm ?? '', d.text_value ?? '', d.entered_unit ?? '', d.verification_status, d.entered_by ?? '', d.date_entered ?? '']));
      return rows.map(r => r.map(c => `"${String(c).replace(/"/g, '""')}"`).join(',')).join('\n');
    }
    return '';
  },
};