import { clean, normalizeStatus } from '../holder-master/holder-master-import';

export type WheelImportRow = {
  sourceId?: number;
  wheelInchValue: number;
  wheelName: string;
  wheelCode: string;
  wheelSize: string;
  wheelSizeCode: string;
  wheelType: string;
  wheelTypeCode: string;
  bearingType: string;
  bearingCode: string;
  dustCoverName: string;
  dustCoverCode: string;
  wheelColor: string;
  wheelColorCode: string;
  dynamicLoadCarryCapacity: string;
  dynamicLoadCarryCapacityCode: string;
  wheelTypeSubName: string;
  wheelTypeSubNameCode: string;
  status: string;
};

export type WheelImportResult = {
  rows: WheelImportRow[];
  errors: string[];
};

type RawRow = Record<string, string>;

const headerMap: Record<string, keyof WheelImportRow> = {
  ID: 'sourceId',
  WHEELNAME: 'wheelName',
  WHEELCODE: 'wheelCode',
  WHEELSIZE: 'wheelSize',
  WHEELSIZECODE: 'wheelSizeCode',
  WHEELTYPE: 'wheelType',
  WHEELTYPECODE: 'wheelTypeCode',
  BEARINGTYPE: 'bearingType',
  BEARINGCODE: 'bearingCode',
  DUSTCOVERNAME: 'dustCoverName',
  DUSTCOVERCODE: 'dustCoverCode',
  WHEELCOLOR: 'wheelColor',
  WHEELCOLORCODE: 'wheelColorCode',
  DYNAMICLOADCARRYCAPACITY: 'dynamicLoadCarryCapacity',
  DYNAMICLOADCARRYCAPACITYCODE: 'dynamicLoadCarryCapacityCode',
  WHEELTYPESUBNAME: 'wheelTypeSubName',
  WHEELTYPESUBNAMECODE: 'wheelTypeSubNameCode',
  STATUS: 'status',
};

export const wheelCsvHeaders = [
  'Id',
  'WHEEL NAME',
  'WHEEL CODE',
  'WHEEL SIZE',
  'WHEEL SIZE CODE',
  'WHEEL TYPE',
  'WHEEL TYPE CODE',
  'BEARING TYPE',
  'BEARING CODE',
  'DUST COVER NAME',
  'DUST COVER CODE',
  'WHEEL COLOR',
  'WHEEL COLOR CODE',
  'DYNAMIC LOAD CARRY CAPACITY',
  'DYNAMIC LOAD CARRY CAPACITY CODE',
  'WHEEL TYPE SUB NAME',
  'WHEEL TYPE SUB NAME CODE',
  'STATUS',
];

export function parseWheelImport(text: string): WheelImportResult {
  const delimiter = detectDelimiter(text);
  const rows = parseDelimited(text, delimiter);
  const [headers = [], ...records] = rows;
  const normalizedHeaders = headers.map(normalizeHeader);
  const result: WheelImportRow[] = [];
  const errors: string[] = [];

  records.forEach((record, rowIndex) => {
    const raw: RawRow = {};

    normalizedHeaders.forEach((header, index) => {
      if (!header || !headerMap[header]) {
        return;
      }

      raw[headerMap[header]] = clean(record[index]);
    });

    if (Object.values(raw).every((value) => !value)) {
      return;
    }

    const rowNumber = rowIndex + 2;
    const wheelName = clean(raw.wheelName);
    const wheelCode = clean(raw.wheelCode).toUpperCase();

    if (!wheelName) {
      errors.push(`Row ${rowNumber}: WHEEL NAME is required.`);
    }

    if (!wheelCode) {
      errors.push(`Row ${rowNumber}: WHEEL CODE is required.`);
    }

    if (!wheelName || !wheelCode) {
      return;
    }

    result.push({
      sourceId: parseInteger(raw.sourceId),
      wheelInchValue: parseWheelInchValue(raw.wheelSize),
      wheelName,
      wheelCode,
      wheelSize: clean(raw.wheelSize),
      wheelSizeCode: clean(raw.wheelSizeCode).toUpperCase(),
      wheelType: clean(raw.wheelType),
      wheelTypeCode: clean(raw.wheelTypeCode).toUpperCase(),
      bearingType: clean(raw.bearingType),
      bearingCode: clean(raw.bearingCode).toUpperCase(),
      dustCoverName: clean(raw.dustCoverName),
      dustCoverCode: clean(raw.dustCoverCode).toUpperCase(),
      wheelColor: clean(raw.wheelColor),
      wheelColorCode: clean(raw.wheelColorCode).toUpperCase(),
      dynamicLoadCarryCapacity: clean(raw.dynamicLoadCarryCapacity),
      dynamicLoadCarryCapacityCode: clean(raw.dynamicLoadCarryCapacityCode).toUpperCase(),
      wheelTypeSubName: clean(raw.wheelTypeSubName),
      wheelTypeSubNameCode: clean(raw.wheelTypeSubNameCode).toUpperCase(),
      status: normalizeStatus(raw.status),
    });
  });

  return { rows: result, errors };
}

export function parseWheelInchValue(value?: string): number {
  const match = clean(value).match(/(\d+(?:\.\d+)?)/);

  if (!match) {
    return 0;
  }

  const sizeMm = Number.parseFloat(match[1]);

  if (!Number.isFinite(sizeMm)) {
    return 0;
  }

  if (sizeMm <= 55) {
    return 2;
  }
  if (sizeMm <= 70) {
    return 2.5;
  }
  if (sizeMm <= 85) {
    return 3;
  }
  if (sizeMm <= 110) {
    return 4;
  }
  if (sizeMm <= 135) {
    return 5;
  }
  if (sizeMm <= 170) {
    return 6;
  }
  if (sizeMm <= 220) {
    return 8;
  }
  if (sizeMm <= 270) {
    return 10;
  }
  if (sizeMm <= 320) {
    return 12;
  }
  if (sizeMm <= 370) {
    return 14;
  }

  return 15;
}

function detectDelimiter(text: string): ',' | '\t' {
  const firstLine = text.split(/\r?\n/, 1)[0] || '';
  const tabCount = (firstLine.match(/\t/g) || []).length;
  const commaCount = (firstLine.match(/,/g) || []).length;
  return tabCount > commaCount ? '\t' : ',';
}

function normalizeHeader(header: string): string {
  return clean(header).replace(/[^a-z0-9]/gi, '').toUpperCase();
}

function parseInteger(value?: string): number | undefined {
  const parsed = Number.parseInt(clean(value), 10);
  return Number.isFinite(parsed) ? parsed : undefined;
}

function parseDelimited(text: string, delimiter: ',' | '\t'): string[][] {
  const rows: string[][] = [];
  let current = '';
  let row: string[] = [];
  let inQuotes = false;

  for (let index = 0; index < text.length; index += 1) {
    const character = text[index];
    const nextCharacter = text[index + 1];

    if (character === '"' && inQuotes && nextCharacter === '"') {
      current += '"';
      index += 1;
      continue;
    }

    if (character === '"') {
      inQuotes = !inQuotes;
      continue;
    }

    if (character === delimiter && !inQuotes) {
      row.push(current);
      current = '';
      continue;
    }

    if ((character === '\n' || character === '\r') && !inQuotes) {
      if (character === '\r' && nextCharacter === '\n') {
        index += 1;
      }

      row.push(current);
      rows.push(row);
      row = [];
      current = '';
      continue;
    }

    current += character;
  }

  if (current || row.length) {
    row.push(current);
    rows.push(row);
  }

  return rows;
}
