import { defineStore } from 'pinia';
import { ref, watch } from 'vue';

export interface KeyValue {
  id: string;
  key: string;
  value: string;
  enabled: boolean;
}

export interface AuthState {
  type: 'none' | 'basic' | 'bearer' | 'api_key';
  basic: { username: '', password: '' };
  bearer: { token: '' };
  apiKey: { key: '', value: '', addTo: 'header' | 'query' };
}

export interface RequestData {
  id: string;
  method: string;
  url: string;
  params: KeyValue[];
  headers: KeyValue[];
  body: string;
  auth: AuthState;
  response?: {
    status: number;
    headers: Record<string, string>;
    body: string;
    time: number;
    size: number;
    headersSize: number;
    bodySize: number;
  };
  timestamp: number;
}

export interface RequestError {
  code: string;
  message: string;
}

const createEmptyKeyValue = (): KeyValue => ({
  id: crypto.randomUUID(),
  key: '',
  value: '',
  enabled: true,
});

const createDefaultAuthState = (): AuthState => ({
  type: 'none',
  basic: { username: '', password: '' },
  bearer: { token: '' },
  apiKey: { key: '', value: '', addTo: 'header' },
});

const createDefaultRequest = (): RequestData => ({
  id: crypto.randomUUID(),
  method: 'GET',
  url: '',
  params: [createEmptyKeyValue()],
  headers: [createEmptyKeyValue()],
  body: '',
  auth: createDefaultAuthState(),
  timestamp: Date.now(),
});

const cloneKeyValueList = (items: KeyValue[] | undefined): KeyValue[] => {
  if (!Array.isArray(items) || items.length === 0) return [];
  return items.map((item) => ({
    id: item.id || crypto.randomUUID(),
    key: item.key || '',
    value: item.value || '',
    enabled: item.enabled ?? true,
  }));
};

const cloneAuthState = (auth: Partial<AuthState> | undefined): AuthState => ({
  type: auth?.type || 'none',
  basic: {
    username: auth?.basic?.username || '',
    password: auth?.basic?.password || '',
  },
  bearer: {
    token: auth?.bearer?.token || '',
  },
  apiKey: {
    key: auth?.apiKey?.key || '',
    value: auth?.apiKey?.value || '',
    addTo: auth?.apiKey?.addTo || 'header',
  },
});

const cloneRequest = (req: Partial<RequestData>): RequestData => ({
  id: typeof req.id === 'string' && req.id ? req.id : crypto.randomUUID(),
  method: req.method || 'GET',
  url: req.url || '',
  params: cloneKeyValueList(req.params),
  headers: cloneKeyValueList(req.headers),
  body: req.body || '',
  auth: cloneAuthState(req.auth),
  response: req.response
    ? {
        status: req.response.status,
        headers: { ...req.response.headers },
        body: req.response.body,
        time: req.response.time,
        size: req.response.size,
        headersSize: req.response.headersSize ?? 0,
        bodySize: req.response.bodySize ?? req.response.body.length,
      }
    : undefined,
  timestamp: typeof req.timestamp === 'number' ? req.timestamp : Date.now(),
});

const normalizeHistoryItem = (item: Partial<RequestData>): RequestData => {
  const cloned = cloneRequest(item);

  return {
    id: cloned.id,
    method: cloned.method,
    url: cloned.url,
    params: cloned.params.length > 0
      ? cloned.params
      : [createEmptyKeyValue()],
    headers: cloned.headers.length > 0
      ? cloned.headers
      : [createEmptyKeyValue()],
    body: cloned.body,
    auth: cloned.auth,
    response: cloned.response,
    timestamp: cloned.timestamp,
  };
};

export const useRequestStore = defineStore('request', () => {
  // State
  const history = ref<RequestData[]>([]);
  const activeRequest = ref<RequestData>(createDefaultRequest());
  const requestError = ref<RequestError | null>(null);

  // Load history from local storage
  const savedHistory = localStorage.getItem('request_history');
  if (savedHistory) {
    try {
      const parsed = JSON.parse(savedHistory);
      history.value = Array.isArray(parsed)
        ? parsed.map((item) => normalizeHistoryItem(item))
        : [];
    } catch (e) {
      console.error('Failed to parse history', e);
    }
  }

  // Actions
  const addToHistory = (req: RequestData) => {
    const newEntry = cloneRequest(req);
    newEntry.id = crypto.randomUUID();
    newEntry.timestamp = Date.now();
    newEntry.params = newEntry.params.filter((p) => p.key.trim() !== '');
    newEntry.headers = newEntry.headers.filter((h) => h.key.trim() !== '');

    history.value.unshift(newEntry);
    if (history.value.length > 50) {
      history.value.pop();
    }
  };

  const clearHistory = () => {
    history.value = [];
  };

  const deleteHistoryItem = (id: string) => {
    const index = history.value.findIndex(item => item.id === id);
    if (index !== -1) {
      history.value.splice(index, 1);
    }
  };

  const resetActiveRequest = () => {
    activeRequest.value = createDefaultRequest();
    requestError.value = null;
  };

  const loadRequest = (req: RequestData) => {
    const loaded = normalizeHistoryItem(cloneRequest(req));
    loaded.id = crypto.randomUUID();
    if (loaded.params.length === 0) loaded.params.push(createEmptyKeyValue());
    if (loaded.headers.length === 0) loaded.headers.push(createEmptyKeyValue());

    activeRequest.value = loaded;
    requestError.value = null;
  };

  const setRequestError = (error: RequestError | null) => {
    requestError.value = error;
  };

  // Watch and Save
  watch(history, (newVal) => {
    localStorage.setItem('request_history', JSON.stringify(newVal));
  }, { deep: true });

  return {
    history,
    activeRequest,
    requestError,
    addToHistory,
    clearHistory,
    deleteHistoryItem,
    loadRequest,
    resetActiveRequest,
    setRequestError,
  };
});
