/**
 * Bas-parser för receptsidor
 * Alla site-specifika parsers bör extenda denna
 */
export interface ParsedRecipe {
  name: string;
  description?: string;
  ingredients: Array<{
    quantity: number;
    unit: string;
    name: string;
    note?: string;
  }>;
  instructions?: string;
  imageUrl?: string;
}

export abstract class RecipeParser {
  /**
   * Kontrollera om denna parser kan hantera denna URL
   */
  abstract canHandle(url: string): boolean;

  /**
   * Parsa HTML och extrahera receptdata
   */
  abstract parse(html: string): ParsedRecipe;

  /**
   * Hjälpfunktion: parsa ingrediens-rad
   * Hanterar format som:
   * - "3 ägg"
   * - "150 g lax"
   * - "1/2 citron"
   * - "1 msk senap"
   * - "salt och peppar"
   * - "1 förp handskalade räkor i lake (à 570 g)"
   */
  protected parseIngredientLine(line: string): {
    quantity: number;
    unit: string;
    name: string;
    note?: string;
  } | null {
    let cleaned = line.replace(/<[^>]+>/g, '').trim();
    if (!cleaned) return null;

    // Kända enheter
    const knownUnits = [
      'g', 'kg', 'hg', 'mg', 'ml', 'dl', 'l', 'tl',
      'st', 'tsk', 'msk', 'krm', 'matsked', 'tesked',
      'pris', 'portion', 'port', 'burk', 'förp', 'paket', 'efter smak', 'klyfta',
    ];

    // Extrahera parentetisk info
    let parentheticalText = '';
    const parentheteMatch = cleaned.match(/\s*\(([^)]*)\)/);
    if (parentheteMatch) {
      parentheticalText = parentheteMatch[1].trim();
      cleaned = cleaned.replace(/\s*\([^)]*\)/, '').trim();
    }

    // Hantera bråkdelar: "1/2" eller "1 1/2" eller "1 1 / 2"
    // Regex: (optional whole)? numerator / denominator
    const fractionMatch = cleaned.match(/^(\d+)?\s*(\d+)\s*\/\s*([\d.]+)/);
    let quantity = 0;
    let remainingText = cleaned;

    if (fractionMatch) {
      if (fractionMatch[1]) {
        // Heltal + bråk: "1 1/2"
        const whole = parseFloat(fractionMatch[1]);
        const numerator = parseFloat(fractionMatch[2]);
        const denominator = parseFloat(fractionMatch[3]);
        quantity = whole + (numerator / denominator);
      } else {
        // Bara bråk: "1/2"
        const numerator = parseFloat(fractionMatch[2]);
        const denominator = parseFloat(fractionMatch[3]);
        quantity = numerator / denominator;
      }
      remainingText = cleaned.substring(fractionMatch[0].length).trim();
    } else {
      const numberMatch = remainingText.match(/^([\d.,]+)/);
      if (numberMatch) {
        quantity = parseFloat(numberMatch[1].replace(',', '.'));
        remainingText = remainingText.substring(numberMatch[0].length).trim();
      }
    }

    // Extrahera potentiell enhet
    let potentialUnit = '';
    let productName = remainingText;

    if (remainingText) {
      const unitMatch = remainingText.match(/^([a-zåäö]+)\b/i);
      if (unitMatch) {
        const candidateUnit = unitMatch[1].toLowerCase();
        if (knownUnits.includes(candidateUnit)) {
          potentialUnit = candidateUnit;
          productName = remainingText.substring(candidateUnit.length).trim();
        }
      }
    }

    // Analysera parenthetical text för måttenhet
    let parenthHasUnit = false;
    if (parentheticalText) {
      for (const unit of knownUnits) {
        if (parentheticalText.toLowerCase().includes(unit)) {
          parenthHasUnit = true;
          break;
        }
      }
    }

    let note: string | undefined = undefined;

    // Om vi hade quantity i huvuddelen och parenthetical innehåller unit
    // → spara parenthetical som note
    if (quantity > 0 && parenthHasUnit) {
      note = parentheticalText;
    }

    // Om ingen mängd i huvuddelen men parenthetical hade både mängd och unit
    // → parse parenthetical som quantity + unit
    if (quantity === 0 && parentheticalText) {
      const parenthMatch = parentheticalText.match(/^[\D]*?([\d.,]+)?\s*([a-zåäö]*)?\s*(.*)$/i);
      if (parenthMatch) {
        let pQuantity = parenthMatch[1] ? parseFloat(parenthMatch[1].replace(',', '.')) : 0;
        let pUnit = parenthMatch[2]?.toLowerCase() || '';
        let pRest = parenthMatch[3]?.trim() || '';

        if (knownUnits.includes(pUnit) && pQuantity > 0) {
          quantity = pQuantity;
          potentialUnit = pUnit;
          note = parentheticalText;
        }
      }
    }

    // Om ingen mängd och enhet, bara returna produktnamnet
    if (quantity === 0) {
      return {
        quantity: 0,
        unit: '',
        name: cleaned,
        note: parentheticalText || undefined,
      };
    }

    return {
      quantity,
      unit: potentialUnit,
      name: productName,
      note: note,
    };
  }
}
