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

/**
 * @typedef {Object} TestMapHeader
 * @property {number} TestMapID - Mapping ID
 * @property {string} HostType - Host Type (HIS, SITE, WST, INST)
 * @property {string} HostID - Host ID
 * @property {string} HostName - Host Name
 * @property {string} ClientType - Client Type (HIS, SITE, WST, INST)
 * @property {string} ClientID - Client ID
 * @property {string} ClientName - Client Name
 * @property {string} IsActive - Active status ('1' or '0')
 */

/**
 * @typedef {Object} TestMapDetail
 * @property {number} TestMapDetailID - Detail ID
 * @property {number} TestMapID - Test Map ID (header)
 * @property {number} TestSiteID - Test Site ID
 * @property {string} TestSiteCode - Test Code
 * @property {string} TestSiteName - Test Name
 * @property {string} HostTestCode - Host Test Code
 * @property {string} HostTestName - Host Test Name
 * @property {number} ConDefID - Container Definition ID
 * @property {string} ClientTestCode - Client Test Code
 * @property {string} ClientTestName - Client Test Name
 * @property {string} IsActive - Active status ('1' or '0')
 */

/**
 * @typedef {Object} TestMapWithDetails
 * @property {number} TestMapID - Mapping ID
 * @property {number} TestSiteID - Test Site ID
 * @property {string} TestSiteCode - Test Code
 * @property {string} TestSiteName - Test Name
 * @property {string} HostType - Host Type
 * @property {string} HostID - Host ID
 * @property {string} HostTestCode - Host Test Code
 * @property {string} HostTestName - Host Test Name
 * @property {string} ClientType - Client Type
 * @property {string} ClientID - Client ID
 * @property {number} ConDefID - Container Definition ID
 * @property {string} ClientTestCode - Client Test Code
 * @property {string} ClientTestName - Client Test Name
 * @property {string} IsActive - Active status ('1' or '0')
 * @property {TestMapDetail[]} details - Array of detail records
 */

/**
 * @typedef {Object} TestMapListResponse
 * @property {boolean} success
 * @property {TestMapHeader[]} data
 * @property {string} [message]
 */

/**
 * @typedef {Object} TestMapResponse
 * @property {boolean} success
 * @property {TestMapWithDetails} data
 * @property {string} [message]
 */

/**
 * @typedef {Object} TestMapDetailResponse
 * @property {boolean} success
 * @property {TestMapDetail} data
 * @property {string} [message]
 */

/**
 * @typedef {Object} CreateTestMapPayload
 * @property {number} TestSiteID - Test Site ID
 * @property {string} HostType - Host Type
 * @property {string} HostID - Host ID
 * @property {string} ClientType - Client Type
 * @property {string} ClientID - Client ID
 * @property {Object[]} [details] - Optional detail records to create
 */

/**
 * @typedef {Object} UpdateTestMapPayload
 * @property {number} TestMapID - Mapping ID
 * @property {number} [TestSiteID] - Test Site ID
 * @property {string} [HostType] - Host Type
 * @property {string} [HostID] - Host ID
 * @property {string} [ClientType] - Client Type
 * @property {string} [ClientID] - Client ID
 */

/**
 * @typedef {Object} CreateTestMapDetailPayload
 * @property {number} TestMapID - Test Map ID
 * @property {string} HostTestCode - Host Test Code
 * @property {string} HostTestName - Host Test Name
 * @property {number} ConDefID - Container Definition ID
 * @property {string} ClientTestCode - Client Test Code
 * @property {string} ClientTestName - Client Test Name
 */

/**
 * @typedef {Object} UpdateTestMapDetailPayload
 * @property {number} TestMapDetailID - Detail ID
 * @property {number} [TestMapID] - Test Map ID
 * @property {string} [HostTestCode] - Host Test Code
 * @property {string} [HostTestName] - Host Test Name
 * @property {number} [ConDefID] - Container Definition ID
 * @property {string} [ClientTestCode] - Client Test Code
 * @property {string} [ClientTestName] - Client Test Name
 */

// ==================== HEADER ENDPOINTS ====================

/**
 * Fetch all test mapping headers (grouped by host/client)
 * @returns {Promise<TestMapListResponse>} API response with headers list
 */
export async function fetchTestMaps() {
  return get('/api/test/testmap');
}

/**
 * Fetch a single test mapping header by ID with details
 * @param {number} id - Test Map ID
 * @returns {Promise<TestMapResponse>} API response with header and details
 */
export async function fetchTestMap(id) {
  return get(`/api/test/testmap/${id}`);
}

/**
 * Fetch test mappings by test site ID with details
 * @param {number} testSiteID - Test Site ID
 * @returns {Promise<TestMapListResponse>} API response with mappings list
 */
export async function fetchTestMapsByTestSite(testSiteID) {
  return get(`/api/test/testmap/by-testsite/${testSiteID}`);
}

/**
 * Create a new test mapping header
 * @param {CreateTestMapPayload} data - Header data
 * @returns {Promise<{success: boolean, data: number, message?: string}>} API response with created TestMapID
 */
export async function createTestMap(data) {
  return post('/api/test/testmap', data);
}

/**
 * Update an existing test mapping header
 * @param {UpdateTestMapPayload} data - Header data
 * @returns {Promise<{success: boolean, data: number, message?: string}>} API response
 */
export async function updateTestMap(id, data) {
  return patch(`/api/test/testmap/${id}`, data);
}

/**
 * Soft delete a test mapping header (cascades to details)
 * @param {number} id - Test Map ID
 * @returns {Promise<{success: boolean, data: number, message?: string}>} API response
 */
export async function deleteTestMap(id) {
  return del('/api/test/testmap', { body: JSON.stringify({ TestMapID: id }) });
}

// ==================== DETAIL ENDPOINTS ====================

/**
 * Fetch all test mapping details (optionally filtered by TestMapID)
 * @param {Object} params - Query parameters
 * @param {number} [params.TestMapID] - Filter by TestMapID
 * @returns {Promise<{success: boolean, data: TestMapDetail[], message?: string}>} API response
 */
export async function fetchTestMapDetails(params = {}) {
  const query = new URLSearchParams();
  if (params.TestMapID) query.append('TestMapID', params.TestMapID.toString());
  const queryString = query.toString();
  return get(queryString ? `/api/test/testmap/detail?${queryString}` : '/api/test/testmap/detail');
}

/**
 * Fetch a single test mapping detail by ID
 * @param {number} id - Test Map Detail ID
 * @returns {Promise<TestMapDetailResponse>} API response with detail
 */
export async function fetchTestMapDetail(id) {
  return get(`/api/test/testmap/detail/${id}`);
}

/**
 * Fetch test mapping details by test map ID
 * @param {number} testMapID - Test Map ID
 * @returns {Promise<{success: boolean, data: TestMapDetail[], message?: string}>} API response
 */
export async function fetchTestMapDetailsByTestMap(testMapID) {
  return get(`/api/test/testmap/detail/by-testmap/${testMapID}`);
}

/**
 * Create a new test mapping detail
 * @param {CreateTestMapDetailPayload} data - Detail data
 * @returns {Promise<{success: boolean, data: number, message?: string}>} API response with created TestMapDetailID
 */
export async function createTestMapDetail(data) {
  return post('/api/test/testmap/detail', data);
}

/**
 * Update an existing test mapping detail
 * @param {UpdateTestMapDetailPayload} data - Detail data
 * @returns {Promise<{success: boolean, message?: string}>} API response
 */
export async function updateTestMapDetail(id, data) {
  return patch(`/api/test/testmap/detail/${id}`, data);
}

/**
 * Soft delete a test mapping detail
 * @param {number} id - Test Map Detail ID
 * @returns {Promise<{success: boolean, message?: string}>} API response
 */
export async function deleteTestMapDetail(id) {
  return del('/api/test/testmap/detail', { body: JSON.stringify({ TestMapDetailID: id }) });
}

// ==================== BATCH DETAIL ENDPOINTS ====================

/**
 * Batch create test mapping details
 * @param {CreateTestMapDetailPayload[]} details - Array of detail records to create
 * @returns {Promise<{success: boolean, message?: string}>} API response
 */
export async function batchCreateTestMapDetails(details) {
  return post('/api/test/testmap/detail/batch', details);
}

/**
 * Batch update test mapping details
 * @param {UpdateTestMapDetailPayload[]} details - Array of detail records to update
 * @returns {Promise<{success: boolean, message?: string}>} API response
 */
export async function batchUpdateTestMapDetails(details) {
  return patch('/api/test/testmap/detail/batch', details);
}

/**
 * Batch delete test mapping details
 * @param {number[]} detailIDs - Array of TestMapDetailID to delete
 * @returns {Promise<{success: boolean, message?: string}>} API response
 */
export async function batchDeleteTestMapDetails(detailIDs) {
  return del('/api/test/testmap/detail/batch', { body: JSON.stringify(detailIDs) });
}

// ==================== VALIDATION ====================

/**
 * Validate mapping form data
 * @param {Object} data - Form data to validate
 * @returns {{valid: boolean, errors: Object}}
 */
export function validateTestMap(data) {
  const errors = {};

  if (!data.TestSiteID) {
    errors.TestSiteID = 'Test is required';
  }

  if (!data.HostType) {
    errors.HostType = 'Host Type is required';
  }

  if (!data.HostID) {
    errors.HostID = 'Host ID is required';
  }

  if (!data.ClientType) {
    errors.ClientType = 'Client Type is required';
  }

  if (!data.ClientID) {
    errors.ClientID = 'Client ID is required';
  }

  return {
    valid: Object.keys(errors).length === 0,
    errors
  };
}

/**
 * Validate detail form data
 * @param {Object} data - Form data to validate
 * @returns {{valid: boolean, errors: Object}}
 */
export function validateTestMapDetail(data) {
  const errors = {};

  if (!data.TestMapID) {
    errors.TestMapID = 'Test Map ID is required';
  }

  const hasAnyField = data.HostTestCode || data.HostTestName || data.ClientTestCode || data.ClientTestName;
  if (!hasAnyField) {
    errors.empty = 'At least one field must be filled';
  }

  return {
    valid: Object.keys(errors).length === 0,
    errors
  };
}
