import { get, post, patch } from './client.js';

/**
 * @typedef {import('$lib/types/test.types.js').TestSummary} TestSummary
 * @typedef {import('$lib/types/test.types.js').TestDetail} TestDetail
 * @typedef {import('$lib/types/test.types.js').CreateTestPayload} CreateTestPayload
 * @typedef {import('$lib/types/test.types.js').UpdateTestPayload} UpdateTestPayload
 * @typedef {import('$lib/types/test.types.js').TestListResponse} TestListResponse
 * @typedef {import('$lib/types/test.types.js').TestDetailResponse} TestDetailResponse
 * @typedef {import('$lib/types/test.types.js').CreateTestResponse} CreateTestResponse
 * @typedef {import('$lib/types/test.types.js').UpdateTestResponse} UpdateTestResponse
 * @typedef {import('$lib/types/test.types.js').DeleteTestResponse} DeleteTestResponse
 * @typedef {import('$lib/types/test.types.js').TestFilterOptions} TestFilterOptions
 */

/**
 * Fetch tests list with optional filters, pagination, and search
 * @param {TestFilterOptions & { page?: number, perPage?: number }} [params] - Query parameters
 * @returns {Promise<TestListResponse>} API response with test data and pagination
 */
export async function fetchTests(params = {}) {
  const query = new URLSearchParams(params).toString();
  return get(query ? `/api/test?${query}` : '/api/test');
}

/**
 * Fetch a single test by ID
 * @param {number} id - Test Site ID
 * @returns {Promise<TestDetailResponse>} API response with test detail
 */
export async function fetchTest(id) {
  return get(`/api/test/${id}`);
}

/**
 * Build payload from form state for API submission
 * Follows the specification: nested details object for technical fields
 * @param {any} formData - The form state
 * @param {boolean} isUpdate - Whether this is an update operation
 * @returns {CreateTestPayload | UpdateTestPayload}
 */
function buildPayload(formData, isUpdate = false) {
  /** @type {CreateTestPayload} */
  const payload = {
    SiteID: formData.SiteID || 1,
    TestSiteCode: formData.TestSiteCode,
    TestSiteName: formData.TestSiteName,
    TestType: formData.TestType,
    Description: formData.Description,
    SeqScr: parseInt(formData.SeqScr) || 0,
    SeqRpt: parseInt(formData.SeqRpt) || 0,
    VisibleScr: formData.VisibleScr ? 1 : 0,
    VisibleRpt: formData.VisibleRpt ? 1 : 0,
    CountStat: formData.CountStat ? 1 : 0,
    Requestable: formData.Requestable ? 1 : 0,
    // StartDate is auto-set by backend (created_at)
    details: {},
    refnum: [],
    reftxt: [],
    testmap: []
  };

  // Add TestSiteID for updates
  if (isUpdate && formData.TestSiteID) {
    payload.TestSiteID = formData.TestSiteID;
  }

  // Build details object based on TestType
  const type = formData.TestType;

  // Common fields for TEST, PARAM, CALC
  if (['TEST', 'PARAM', 'CALC'].includes(type)) {
    payload.details = {
      DisciplineID: formData.details?.DisciplineID || null,
      DepartmentID: formData.details?.DepartmentID || null,
      ResultType: formData.details?.ResultType || '',
      RefType: formData.details?.RefType || '',
      VSet: formData.details?.VSet || '',
      Unit1: formData.details?.Unit1 || '',
      Factor: formData.details?.Factor || null,
      Unit2: formData.details?.Unit2 || '',
      Decimal: formData.details?.Decimal || 2,
      ReqQty: formData.details?.ReqQty || null,
      ReqQtyUnit: formData.details?.ReqQtyUnit || '',
      CollReq: formData.details?.CollReq || '',
      Method: formData.details?.Method || '',
      ExpectedTAT: formData.details?.ExpectedTAT || null
    };

    // Add formula fields for CALC type
    if (type === 'CALC') {
      payload.details.FormulaCode = formData.details?.FormulaCode || '';

      const calcMembers = formData.testdefgrp || formData.details?.members || [];
      if (calcMembers.length > 0) {
        payload.details.members = calcMembers.map(m => ({
          TestSiteID: m.TestSiteID,
          Member: m.Member || m.TestSiteID
        }));
      }
    }
  }

  // Add members for GROUP type
  if (type === 'GROUP') {
    const groupMembers = formData.testdefgrp || formData.details?.members || [];
    payload.details = {
      members: groupMembers.map(m => ({
        TestSiteID: m.TestSiteID,
        Member: m.Member || m.TestSiteID
      }))
    };
  }

  // Add reference ranges (TEST and PARAM only)
  if (['TEST', 'PARAM'].includes(type)) {
    if (formData.refnum && Array.isArray(formData.refnum)) {
      payload.refnum = formData.refnum.map(r => ({
        NumRefType: r.NumRefType,
        RangeType: r.RangeType,
        Sex: r.Sex,
        AgeStart: parseInt(r.AgeStart) || 0,
        AgeEnd: parseInt(r.AgeEnd) || 54750, // 150 years in days
        LowSign: r.LowSign || null,
        Low: r.Low !== null && r.Low !== undefined ? parseFloat(r.Low) : null,
        HighSign: r.HighSign || null,
        High: r.High !== null && r.High !== undefined ? parseFloat(r.High) : null,
        Flag: r.Flag || null,
        Interpretation: r.Interpretation || null
      }));
    }

    if (formData.reftxt && Array.isArray(formData.reftxt)) {
      payload.reftxt = formData.reftxt.map(r => ({
        TxtRefType: r.TxtRefType,
        Sex: r.Sex,
        AgeStart: parseInt(r.AgeStart) || 0,
        AgeEnd: parseInt(r.AgeEnd) || 54750, // 150 years in days
        RefTxt: r.RefTxt || '',
        Flag: r.Flag || null
      }));
    }
  }

  // Add mappings (all types)
  if (formData.testmap && Array.isArray(formData.testmap)) {
    payload.testmap = formData.testmap.map(m => ({
      HostType: m.HostType || null,
      HostID: m.HostID || null,
      HostDataSource: m.HostDataSource || null,
      HostTestCode: m.HostTestCode || null,
      HostTestName: m.HostTestName || null,
      ClientType: m.ClientType || null,
      ClientID: m.ClientID || null,
      ClientDataSource: m.ClientDataSource || null,
      ConDefID: m.ConDefID || null,
      ClientTestCode: m.ClientTestCode || null,
      ClientTestName: m.ClientTestName || null
    }));
  }

  return payload;
}

/**
 * Create a new test
 * @param {any} formData - The form state
 * @returns {Promise<CreateTestResponse>} API response
 */
export async function createTest(formData) {
  const payload = buildPayload(formData, false);
  return post('/api/test', payload);
}

/**
 * Update an existing test
 * @param {any} formData - The form state
 * @returns {Promise<UpdateTestResponse>} API response
 */
export async function updateTest(id, formData) {
  const payload = buildPayload(formData, true);
  return patch(`/api/test/${id}`, payload);
}

/**
 * Soft delete a test (set IsActive to '0')
 * @param {number} id - Test Site ID
 * @returns {Promise<DeleteTestResponse>} API response
 */
export async function deleteTest(id) {
return patch('/api/test', {
    TestSiteID: id,
    IsActive: '0',
  });
}

/**
 * Validate test type combination
 * According to business rules: TestType + ResultType + RefType must be valid
 * @param {string} testType - The test type
 * @param {string} resultType - The result type
 * @param {string} refType - The reference type
 * @returns {{ valid: boolean, error?: string }}
 */
export function validateTypeCombination(testType, resultType, refType) {
  // Valid combinations based on specification
  const validCombinations = {
    TEST: {
      NMRIC: ['RANGE', 'THOLD'],
      RANGE: ['RANGE', 'THOLD'],
      TEXT: ['TEXT'],
      VSET: ['VSET']
    },
    PARAM: {
      NMRIC: ['RANGE', 'THOLD'],
      RANGE: ['RANGE', 'THOLD'],
      TEXT: ['TEXT'],
      VSET: ['VSET']
    },
    CALC: {
      NMRIC: ['RANGE', 'THOLD']
    },
    GROUP: {
      NORES: ['NOREF']
    },
    TITLE: {
      NORES: ['NOREF']
    }
  };

  const validResultTypes = validCombinations[testType];
  if (!validResultTypes) {
    return { valid: false, error: 'Invalid test type' };
  }

  if (!resultType) {
    return { valid: true }; // ResultType might be optional
  }

  const validRefTypes = validResultTypes[resultType];
  if (!validRefTypes) {
    return { valid: false, error: `Result type '${resultType}' is not valid for '${testType}'` };
  }

  if (refType && !validRefTypes.includes(refType)) {
    return { valid: false, error: `Reference type '${refType}' is not valid for '${testType}' + '${resultType}'` };
  }

  return { valid: true };
}

/**
 * Get valid result types for a test type
 * @param {string} testType - The test type
 * @returns {Array<{value: string, label: string}>}
 */
export function getResultTypeOptions(testType) {
  switch (testType) {
    case 'CALC':
      return [{ value: 'NMRIC', label: 'Numeric' }];
    case 'GROUP':
    case 'TITLE':
      return [{ value: 'NORES', label: 'No Result' }];
    default:
      return [
        { value: 'NMRIC', label: 'Numeric' },
        { value: 'RANGE', label: 'Range' },
        { value: 'TEXT', label: 'Text' },
        { value: 'VSET', label: 'Value Set' }
      ];
  }
}

/**
 * Get valid reference types for a result type
 * @param {string} resultType - The result type
 * @returns {Array<{value: string, label: string}>}
 */
export function getRefTypeOptions(resultType) {
  switch (resultType) {
    case 'NMRIC':
    case 'RANGE':
      return [
        { value: 'RANGE', label: 'Range' },
        { value: 'THOLD', label: 'Threshold' }
      ];
    case 'VSET':
      return [{ value: 'VSET', label: 'Value Set' }];
    case 'TEXT':
      return [{ value: 'TEXT', label: 'Text' }];
    case 'NORES':
      return [{ value: 'NOREF', label: 'No Reference' }];
    default:
      return [];
  }
}

/**
 * Validate test code according to specification
 * - Required
 * - 3-6 characters
 * - Uppercase alphanumeric only
 * - Regex: ^[A-Z0-9]{3,6}$
 * @param {string} code - The test code
 * @returns {{ valid: boolean, error?: string }}
 */
export function validateTestCode(code) {
  if (!code || code.trim() === '') {
    return { valid: false, error: 'Test code is required' };
  }

  const trimmed = code.trim();

  const regex = /^[A-Z0-9]+$/;
  if (!regex.test(trimmed)) {
    return { valid: false, error: 'Test code must be uppercase alphanumeric' };
  }

  return { valid: true };
}

/**
 * Validate test name according to specification
 * - Required
 * - 3-255 characters
 * - Alphanumeric with hyphen, space, and parentheses allowed
 * - Regex: ^[a-zA-Z0-9\s\-\(\)]{3,255}$
 * @param {string} name - The test name
 * @returns {{ valid: boolean, error?: string }}
 */
export function validateTestName(name) {
  if (!name || name.trim() === '') {
    return { valid: false, error: 'Test name is required' };
  }

  const trimmed = name.trim();
  if (trimmed.length < 3) {
    return { valid: false, error: 'Test name must be at least 3 characters' };
  }
  if (trimmed.length > 255) {
    return { valid: false, error: 'Test name must be at most 255 characters' };
  }

  const regex = /^[a-zA-Z0-9\s\-\(\)]{3,255}$/;
  if (!regex.test(trimmed)) {
    return { valid: false, error: 'Test name can only contain letters, numbers, spaces, hyphens, and parentheses' };
  }

  return { valid: true };
}
