import { useState } from 'preact/hooks';
import OpenAI from 'openai';

export function useModel(apiKey?: string, baseURL?: string, projectId?: string) {
  const [models, setModels] = useState<string[]>([]);
  const [error, setError] = useState<string | null>(null);

  const isCurrentVersionSupportingImages = (version?: string) => {
    if (!version) return false;
    const versionNumber = version.match(/gpt-(\d+)/);
    if (!versionNumber?.[1]) {
      return false;
    }
    return Number(versionNumber[1]) >= 4;
  };

  const fetchModels = async () => {
    if (!apiKey) return;
    try {
      const client = new OpenAI({
        apiKey,
        baseURL: baseURL || undefined,
        project: projectId || undefined,
        dangerouslyAllowBrowser: true
      });

      const rep = await client.models.list();

      const filteredModels = rep.data.filter(
        model =>
          model.id.startsWith('gpt') ||
          model.id.search(/^o\d+/gi) !== -1 ||
          model.id.startsWith('chatgpt')
      );
      filteredModels.sort((a, b) => b.id.localeCompare(a.id));

      setModels(filteredModels.map(m => m.id));
      setError(null);
    } catch (err: any) {
      console.error(err);
      setError(err.message || String(err));
    }
  };

  const validateModel = async (model: string, maxTokens?: number) => {
    if (!apiKey || !model) return { success: false, error: 'API Key and Model are required' };

    try {
      const client = new OpenAI({
        apiKey,
        baseURL: baseURL || undefined,
        project: projectId || undefined,
        dangerouslyAllowBrowser: true
      });
      const completion = await client.chat.completions.create({
        model,
        messages: [
          {
            role: 'user',
            content:
              'reply just pong, set success to true, and provide a random number between 1 and 100.'
          }
        ],
        max_completion_tokens: maxTokens || 2000,
        response_format: {
          type: 'json_schema',
          json_schema: {
            name: 'model_test',
            strict: true,
            schema: {
              type: 'object',
              properties: {
                reply: { type: 'string', description: 'The text reply' },
                success: { type: 'boolean', description: 'Always true' },
                data: {
                  type: 'object',
                  properties: {
                    number: { type: 'integer' }
                  },
                  required: ['number'],
                  additionalProperties: false
                }
              },
              required: ['reply', 'success', 'data'],
              additionalProperties: false
            }
          }
        }
      });

      const content = completion.choices[0]?.message?.content;
      if (!content) {
        throw new Error('No content returned from the model.');
      }

      const parsed = JSON.parse(content);
      if (
        typeof parsed.reply !== 'string' ||
        typeof parsed.success !== 'boolean' ||
        typeof parsed.data !== 'object' ||
        typeof parsed.data.number !== 'number'
      ) {
        throw new Error('Model did not follow the JSON schema correctly.');
      }

      return { success: true, message: 'The model is valid and supports structured outputs!' };
    } catch (err: any) {
      return { success: false, error: err.message || String(err) };
    }
  };

  return { models, fetchModels, validateModel, error, isCurrentVersionSupportingImages };
}
