import React, { useState, useCallback, useEffect, createContext, useContext, ReactNode } from 'react';
import ReactDOM from 'react-dom/client';

// --- TYPES ---
interface UserProfile {
    id: string;
    username: string;
    is_admin: boolean;
    subscription: UserSubscription;
}

interface UserSubscription {
    id: string;
    user_id: string;
    plan_id: string;
    remaining_generations: number;
    token_balance: number;
    expires_at: string;
    is_active: boolean;
}

interface ApiKey {
    id: string;
    name: string;
    user_id: string;
    key_preview: string;
    created_at: string;
    last_used_at: string | null;
}

interface Job {
    id: string;
    user_id: string;
    api_key_id: string;
    job_id: string;
    status: 'PENDING' | 'COMPLETED' | 'FAILED';
    prompt: string;
    request_body: string;
    cost: number;
    created_at: string;
}

interface GenerationParams {
    prompt: string;
    negativePrompt?: string;
    width?: number;
    height?: number;
    step?: number;
    seed?: number;
    count?: number;
    hires?: boolean;
    hiresUpscale?: number;
    adetailer?: boolean;
}

interface CostCalculation {
    totalTokenCost: number;
    generationDiscount: number;
    finalTokenCost: number;
    canUseGeneration: boolean;
    remainingGenerations: number;
    remainingTokens: number;
    hasSufficientCredits: boolean;
}

interface GenerationResponse {
    jobId: string;
    status: string;
    message: string;
}

interface Plan {
    id: string;
    name: string;
    price: number;
    monthlyGenerations: number;
    monthlyTokens: number;
    allowedParams: string[];
    fixedParams: Record<string, any>;
    rateLimits: {
        requestsPerMinute: number;
        requestsPerHour: number;
        requestsPerDay: number;
    };
}

// --- API SERVICE ---
const BASE_URL = 'https://jitome-api.herobrine0991.workers.dev';

class ApiService {
    private async request<T,>(endpoint: string, options: RequestInit = {}): Promise<T> {
        const url = `${BASE_URL}${endpoint}`;
        const response = await fetch(url, options);

        if (!response.ok) {
            const errorData = await response.json().catch(() => ({ message: 'An unknown error occurred' }));
            throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
        }
        return response.json() as Promise<T>;
    }

    // Auth
    async login(username: string, password: string): Promise<{ token: string }> {
        return this.request('/auth/login', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ username, password }),
        });
    }
    
    // Profile
    async getProfile(jwt: string): Promise<UserProfile> {
        return this.request<UserProfile>('/auth/profile', {
            headers: { 'Authorization': `Bearer ${jwt}` }
        });
    }

    // API Keys
    async getApiKeys(jwt: string): Promise<ApiKey[]> {
        return this.request<ApiKey[]>('/auth/api-keys', {
            headers: { 'Authorization': `Bearer ${jwt}` }
        });
    }

    async createApiKey(jwt: string, name: string): Promise<{ key: string, keyData: any }> {
        return this.request('/auth/api-keys', {
            method: 'POST',
            headers: { 
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${jwt}` 
            },
            body: JSON.stringify({ name }),
        });
    }
    
    async deleteApiKey(jwt: string, keyId: string) {
        return this.request(`/auth/api-keys/${keyId}`, {
            method: 'DELETE',
            headers: { 'Authorization': `Bearer ${jwt}` }
        });
    }

    // Jobs
    async getJobs(jwt: string): Promise<Job[]> {
        return this.request<Job[]>('/auth/jobs', {
            headers: { 'Authorization': `Bearer ${jwt}` }
        });
    }

    // Generation
    async calculateCost(apiKey: string, params: GenerationParams): Promise<CostCalculation> {
        return this.request<CostCalculation>('/calculate-cost', {
            method: 'POST',
            headers: { 
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}` 
            },
            body: JSON.stringify(params),
        });
    }
    
    async generateImage(apiKey: string, params: GenerationParams): Promise<GenerationResponse> {
        return this.request<GenerationResponse>('/generate', {
            method: 'POST',
            headers: { 
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}` 
            },
            body: JSON.stringify(params),
        });
    }

    // Admin
    async getPlans(adminJwt: string): Promise<Plan[]> {
        return this.request<Plan[]>('/admin/plans', {
            headers: { 'Authorization': `Bearer ${adminJwt}` }
        });
    }

    async createPlan(adminJwt: string, plan: Omit<Plan, 'rateLimits'> & { rateLimits: any}) {
        return this.request('/admin/plans', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${adminJwt}`
            },
            body: JSON.stringify(plan),
        });
    }

    async updatePlan(adminJwt: string, planId: string, plan: Partial<Plan>) {
        return this.request(`/admin/plans/${planId}`, {
            method: 'PUT',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${adminJwt}`
            },
            body: JSON.stringify(plan),
        });
    }

    async deletePlan(adminJwt: string, planId: string) {
        return this.request(`/admin/plans/${planId}`, {
            method: 'DELETE',
            headers: { 'Authorization': `Bearer ${adminJwt}` }
        });
    }
}

const apiService = new ApiService();


// --- AUTH CONTEXT ---
interface AuthContextType {
    jwt: string | null;
    setJwt: (token: string | null) => void;
    user: UserProfile | null;
    setUser: (user: UserProfile | null) => void;
}

const AuthContext = createContext<AuthContextType | undefined>(undefined);

const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
    const [jwt, setJwt] = useState<string | null>(null);
    const [user, setUser] = useState<UserProfile | null>(null);

    return (
        <AuthContext.Provider value={{ jwt, setJwt, user, setUser }}>
            {children}
        </AuthContext.Provider>
    );
};

const useAuth = (): AuthContextType => {
    const context = useContext(AuthContext);
    if (!context) {
        throw new Error('useAuth must be used within an AuthProvider');
    }
    return context;
};

// --- COMPONENTS ---

// components/auth/LoginPage.tsx
const LoginPage: React.FC = () => {
    const [username, setUsername] = useState('');
    const [password, setPassword] = useState('');
    const [error, setError] = useState('');
    const [isLoading, setIsLoading] = useState(false);
    const { setJwt } = useAuth();

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        setError('');
        setIsLoading(true);
        try {
            const data = await apiService.login(username, password);
            setJwt(data.token);
        } catch (err) {
            setError(err instanceof Error ? err.message : 'Login failed');
        } finally {
            setIsLoading(false);
        }
    };

    return (
        <div className="flex items-center justify-center min-h-screen bg-gray-900">
            <div className="w-full max-w-md p-8 space-y-8 bg-gray-800 rounded-lg shadow-lg">
                <h2 className="text-3xl font-bold text-center text-white">Jitome API Login</h2>
                <form className="space-y-6" onSubmit={handleSubmit}>
                    <div>
                        <label className="block mb-2 text-sm font-medium text-gray-300">Username</label>
                        <input
                            type="text"
                            value={username}
                            onChange={(e) => setUsername(e.target.value)}
                            className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500"
                            required
                        />
                    </div>
                    <div>
                        <label className="block mb-2 text-sm font-medium text-gray-300">Password</label>
                        <input
                            type="password"
                            value={password}
                            onChange={(e) => setPassword(e.target.value)}
                            className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500"
                            required
                        />
                    </div>
                    {error && <p className="text-red-400 text-sm">{error}</p>}
                    <button
                        type="submit"
                        disabled={isLoading}
                        className="w-full px-4 py-2 font-bold text-white bg-indigo-600 rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 disabled:bg-indigo-800 disabled:cursor-not-allowed"
                    >
                        {isLoading ? 'Logging in...' : 'Login'}
                    </button>
                </form>
            </div>
        </div>
    );
};

// components/user/ImageGenerator.tsx
const ImageGenerator: React.FC = () => {
    const { jwt } = useAuth();
    const [apiKeys, setApiKeys] = useState<ApiKey[]>([]);
    const [selectedApiKey, setSelectedApiKey] = useState('');
    const [params, setParams] = useState<GenerationParams>({
        prompt: '',
        negativePrompt: '',
        width: 512,
        height: 768,
        step: 25,
        seed: -1,
        count: 1,
        hires: false,
        hiresUpscale: 1.5,
        adetailer: false,
    });
    const [cost, setCost] = useState<CostCalculation | null>(null);
    const [generationResult, setGenerationResult] = useState<GenerationResponse | null>(null);
    const [error, setError] = useState('');
    const [isLoading, setIsLoading] = useState(false);

    useEffect(() => {
        const fetchKeys = async () => {
            if (jwt) {
                try {
                    const keys = await apiService.getApiKeys(jwt);
                    setApiKeys(keys);
                    if (keys.length > 0) {
                        // We don't get the full key, so we can't set it here.
                        // User needs to provide it.
                    }
                } catch (err) {
                    setError(err instanceof Error ? err.message : 'Failed to fetch API keys');
                }
            }
        };
        fetchKeys();
    }, [jwt]);

    const handleParamChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        const { name, value, type } = e.target;
        
        let processedValue: string | number | boolean = value;
        if (type === 'number') {
           processedValue = value ? parseFloat(value) : 0;
        } else if (type === 'checkbox') {
             processedValue = (e.target as HTMLInputElement).checked;
        }

        setParams(prev => ({ ...prev, [name]: processedValue }));
    };

    const handleAction = async (action: 'cost' | 'generate') => {
        if (!selectedApiKey) {
            setError('Please enter your API Key to proceed.');
            return;
        }
        setError('');
        setCost(null);
        setGenerationResult(null);
        setIsLoading(true);

        try {
            if (action === 'cost') {
                const result = await apiService.calculateCost(selectedApiKey, params);
                setCost(result);
            } else {
                const result = await apiService.generateImage(selectedApiKey, params);
                setGenerationResult(result);
            }
        } catch (err) {
            setError(err instanceof Error ? err.message : `Failed to ${action}`);
        } finally {
            setIsLoading(false);
        }
    };
    
    return (
        <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
            <div className="space-y-4">
                <h3 className="text-xl font-semibold">Generation Parameters</h3>
                
                <div>
                  <label className="block mb-2 text-sm font-medium text-gray-300">API Key</label>
                  <input
                    type="password"
                    placeholder="Enter your API Key (required for actions)"
                    value={selectedApiKey}
                    onChange={(e) => setSelectedApiKey(e.target.value)}
                    className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500"
                  />
                  <p className="text-xs text-gray-500 mt-1">We only show key previews. Please paste your full key here.</p>
                </div>
                
                <div>
                    <label className="block mb-2 text-sm font-medium text-gray-300">Prompt</label>
                    <textarea name="prompt" value={params.prompt} onChange={handleParamChange} rows={3} className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500" />
                </div>
                <div>
                    <label className="block mb-2 text-sm font-medium text-gray-300">Negative Prompt</label>
                    <textarea name="negativePrompt" value={params.negativePrompt} onChange={handleParamChange} rows={2} className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500" />
                </div>
                <div className="grid grid-cols-2 gap-4">
                    <div>
                        <label className="block mb-2 text-sm font-medium text-gray-300">Width</label>
                        <input type="number" name="width" value={params.width} onChange={handleParamChange} className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md"/>
                    </div>
                     <div>
                        <label className="block mb-2 text-sm font-medium text-gray-300">Height</label>
                        <input type="number" name="height" value={params.height} onChange={handleParamChange} className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md"/>
                    </div>
                    <div>
                        <label className="block mb-2 text-sm font-medium text-gray-300">Steps</label>
                        <input type="number" name="step" value={params.step} onChange={handleParamChange} className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md"/>
                    </div>
                     <div>
                        <label className="block mb-2 text-sm font-medium text-gray-300">Seed</label>
                        <input type="number" name="seed" value={params.seed} onChange={handleParamChange} className="w-full px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md"/>
                    </div>
                </div>
                 <div className="flex items-center space-x-4">
                    <label className="flex items-center space-x-2">
                        <input type="checkbox" name="hires" checked={params.hires} onChange={handleParamChange} className="form-checkbox h-5 w-5 text-indigo-600 bg-gray-700 border-gray-600 rounded" />
                        <span>Hires. Fix</span>
                    </label>
                    <label className="flex items-center space-x-2">
                         <input type="checkbox" name="adetailer" checked={params.adetailer} onChange={handleParamChange} className="form-checkbox h-5 w-5 text-indigo-600 bg-gray-700 border-gray-600 rounded" />
                        <span>ADetailer</span>
                    </label>
                </div>

                <div className="flex space-x-4">
                    <button onClick={() => handleAction('cost')} disabled={isLoading} className="flex-1 px-4 py-2 font-bold text-white bg-indigo-600 rounded-md hover:bg-indigo-700 disabled:bg-gray-600">
                        {isLoading ? '...' : 'Calculate Cost'}
                    </button>
                    <button onClick={() => handleAction('generate')} disabled={isLoading} className="flex-1 px-4 py-2 font-bold text-white bg-green-600 rounded-md hover:bg-green-700 disabled:bg-gray-600">
                        {isLoading ? '...' : 'Generate Image'}
                    </button>
                </div>
            </div>

            <div className="space-y-4 p-4 bg-gray-900 rounded-lg">
                 <h3 className="text-xl font-semibold">Result</h3>
                 {error && <div className="p-3 bg-red-900/50 text-red-300 border border-red-500 rounded-md">{error}</div>}
                 
                 {cost && (
                     <div className="p-4 bg-gray-700 rounded-md space-y-2">
                         <h4 className="font-bold">Cost Calculation</h4>
                         <p>Total Token Cost: <span className="font-mono">{cost.totalTokenCost}</span></p>
                         <p>Generation Discount: <span className="font-mono">{cost.generationDiscount}</span></p>
                         <p className="font-bold">Final Token Cost: <span className="font-mono">{cost.finalTokenCost}</span></p>
                         <p>Can Use Generation: <span className={`font-bold ${cost.canUseGeneration ? 'text-green-400' : 'text-red-400'}`}>{cost.canUseGeneration ? 'Yes' : 'No'}</span></p>
                         <hr className="border-gray-600" />
                         <p>Remaining Generations: <span className="font-mono">{cost.remainingGenerations}</span></p>
                         <p>Remaining Tokens: <span className="font-mono">{cost.remainingTokens}</span></p>
                         <p>Has Sufficient Credits: <span className={`font-bold ${cost.hasSufficientCredits ? 'text-green-400' : 'text-red-400'}`}>{cost.hasSufficientCredits ? 'Yes' : 'No'}</span></p>
                     </div>
                 )}

                 {generationResult && (
                     <div className="p-4 bg-gray-700 rounded-md space-y-2">
                         <h4 className="font-bold">Generation Submitted</h4>
                         <p>Status: <span className="font-mono text-yellow-400">{generationResult.status}</span></p>
                         <p>Job ID: <span className="font-mono break-all">{generationResult.jobId}</span></p>
                         <p>Message: {generationResult.message}</p>
                     </div>
                 )}

                 {!isLoading && !cost && !generationResult && !error && (
                    <div className="text-center text-gray-500 p-8">
                        <p>Results will appear here after calculating cost or generating an image.</p>
                    </div>
                 )}
            </div>
        </div>
    );
};

// components/user/ApiKeyManager.tsx
const ApiKeyManager: React.FC = () => {
    const { jwt } = useAuth();
    const [apiKeys, setApiKeys] = useState<ApiKey[]>([]);
    const [newKeyName, setNewKeyName] = useState('');
    const [generatedKey, setGeneratedKey] = useState<string | null>(null);
    const [error, setError] = useState('');
    const [isLoading, setIsLoading] = useState(false);

    const fetchKeys = useCallback(async () => {
        if (!jwt) return;
        setIsLoading(true);
        try {
            const keys = await apiService.getApiKeys(jwt);
            setApiKeys(keys);
        } catch (err) {
            setError(err instanceof Error ? err.message : 'Failed to fetch API keys');
        } finally {
            setIsLoading(false);
        }
    }, [jwt]);

    useEffect(() => {
        fetchKeys();
    }, [fetchKeys]);

    const handleCreateKey = async (e: React.FormEvent) => {
        e.preventDefault();
        if (!jwt || !newKeyName) return;
        setError('');
        setGeneratedKey(null);
        setIsLoading(true);
        try {
            const result = await apiService.createApiKey(jwt, newKeyName);
            setGeneratedKey(result.key);
            setNewKeyName('');
            await fetchKeys(); // Refresh the list
        } catch (err) {
            setError(err instanceof Error ? err.message : 'Failed to create API key');
        } finally {
            setIsLoading(false);
        }
    };
    
    const handleDeleteKey = async (keyId: string) => {
        if (!jwt || !window.confirm('Are you sure you want to delete this key? This action cannot be undone.')) return;
        
        setIsLoading(true);
        try {
            await apiService.deleteApiKey(jwt, keyId);
            await fetchKeys(); // Refresh
        } catch (err) {
             setError(err instanceof Error ? err.message : 'Failed to delete API key');
        } finally {
            setIsLoading(false);
        }
    };

    return (
        <div className="space-y-6">
            <h3 className="text-xl font-semibold">Manage API Keys</h3>

            {error && <p className="p-3 bg-red-900/50 text-red-300 border border-red-500 rounded-md">{error}</p>}
            
            {generatedKey && (
                <div className="p-4 bg-green-900/50 border border-green-500 rounded-md">
                    <h4 className="font-bold text-green-300">New API Key Generated</h4>
                    <p className="text-sm text-yellow-300 my-2">Please copy this key and store it securely. You will not be able to see it again.</p>
                    <div className="p-2 bg-gray-900 rounded font-mono break-all text-green-400">{generatedKey}</div>
                </div>
            )}

            <form onSubmit={handleCreateKey} className="flex flex-col sm:flex-row gap-4 p-4 bg-gray-700/50 rounded-lg">
                <input
                    type="text"
                    value={newKeyName}
                    onChange={(e) => setNewKeyName(e.target.value)}
                    placeholder="New key name (e.g., 'My Awesome App')"
                    className="flex-grow px-3 py-2 text-gray-200 bg-gray-700 border border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500"
                    required
                />
                <button type="submit" disabled={isLoading || !newKeyName} className="px-4 py-2 font-bold text-white bg-indigo-600 rounded-md hover:bg-indigo-700 disabled:bg-gray-600">
                    {isLoading ? 'Creating...' : 'Create New Key'}
                </button>
            </form>

            <div className="space-y-3">
                <h4 className="font-semibold">Your Keys</h4>
                 {isLoading && apiKeys.length === 0 && <p>Loading keys...</p>}
                 {!isLoading && apiKeys.length === 0 && <p className="text-gray-500">You have no API keys.</p>}
                {apiKeys.map(key => (
                    <div key={key.id} className="flex justify-between items-center p-3 bg-gray-700 rounded-md">
                        <div>
                            <p className="font-bold">{key.name}</p>
                            <p className="text-sm text-gray-400 font-mono">ID: {key.id}</p>
                             <p className="text-sm text-gray-400 font-mono">Preview: ...{key.key_preview}</p>
                        </div>
                         <button onClick={() => handleDeleteKey(key.id)} disabled={isLoading} className="px-3 py-1 text-sm font-bold text-white bg-red-600 rounded-md hover:bg-red-700 disabled:bg-gray-600">
                           Delete
                         </button>
                    </div>
                ))}
            </div>
        </div>
    );
};

// components/user/UserProfileDisplay.tsx
const UserProfileDisplay: React.FC = () => {
    const { user } = useAuth();

    if (!user) {
        return <p>Loading profile...</p>;
    }

    return (
        <div className="space-y-6">
            <h3 className="text-xl font-semibold">User Profile</h3>
            <div className="p-4 bg-gray-700/50 rounded-lg grid grid-cols-1 md:grid-cols-2 gap-4">
                <div><span className="font-bold text-gray-400">User ID:</span> <span className="font-mono">{user.id}</span></div>
                <div><span className="font-bold text-gray-400">Username:</span> {user.username}</div>
                <div><span className="font-bold text-gray-400">Role:</span> {user.is_admin ? 'Admin' : 'User'}</div>
            </div>

            <h3 className="text-xl font-semibold">Active Subscription</h3>
             {user.subscription ? (
                 <div className="p-4 bg-gray-700/50 rounded-lg grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div><span className="font-bold text-gray-400">Plan ID:</span> <span className="font-mono">{user.subscription.plan_id}</span></div>
                    <div><span className="font-bold text-gray-400">Status:</span> {user.subscription.is_active ? <span className="text-green-400">Active</span> : <span className="text-red-400">Inactive</span>}</div>
                    <div><span className="font-bold text-gray-400">Remaining Generations:</span> <span className="text-lg font-bold text-indigo-400">{user.subscription.remaining_generations}</span></div>
                    <div><span className="font-bold text-gray-400">Token Balance:</span> <span className="text-lg font-bold text-indigo-400">{user.subscription.token_balance}</span></div>
                    <div><span className="font-bold text-gray-400">Expires At:</span> {new Date(user.subscription.expires_at).toLocaleString()}</div>
                 </div>
             ) : (
                <p className="text-gray-500">No active subscription found.</p>
             )}
        </div>
    );
};

// components/user/JobHistory.tsx
const JobHistory: React.FC = () => {
    const { jwt } = useAuth();
    const [jobs, setJobs] = useState<Job[]>([]);
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState('');

    useEffect(() => {
        const fetchJobs = async () => {
            if (!jwt) return;
            setIsLoading(true);
            setError('');
            try {
                const fetchedJobs = await apiService.getJobs(jwt);
                setJobs(fetchedJobs);
            } catch (err) {
                setError(err instanceof Error ? err.message : 'Failed to fetch job history');
            } finally {
                setIsLoading(false);
            }
        };

        fetchJobs();
    }, [jwt]);

    return (
        <div className="space-y-4">
            <h3 className="text-xl font-semibold">Job History</h3>
            {error && <p className="p-3 bg-red-900/50 text-red-300 border border-red-500 rounded-md">{error}</p>}
            {isLoading && <p>Loading job history...</p>}
            
            {!isLoading && jobs.length === 0 && <p className="text-gray-500">No jobs found.</p>}

            <div className="overflow-x-auto">
                <table className="min-w-full divide-y divide-gray-700">
                    <thead className="bg-gray-800">
                        <tr>
                            <th className="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Job ID</th>
                            <th className="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Prompt</th>
                            <th className="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Status</th>
                            <th className="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Cost</th>
                            <th className="px-6 py-3 text-left text-xs font-medium text-gray-300 uppercase tracking-wider">Created At</th>
                        </tr>
                    </thead>
                    <tbody className="bg-gray-800/50 divide-y divide-gray-700">
                        {jobs.map(job => (
                            <tr key={job.id}>
                                <td className="px-6 py-4 whitespace-nowrap text-sm font-mono text-gray-400" title={job.job_id}>{job.job_id.substring(0, 15)}...</td>
                                <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-300 max-w-xs truncate" title={job.prompt}>{job.prompt}</td>
                                <td className="px-6 py-4 whitespace-nowrap text-sm">
                                    <span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${
                                        job.status === 'COMPLETED' ? 'bg-green-800 text-green-200' : 
                                        job.status === 'PENDING' ? 'bg-yellow-800 text-yellow-200' : 
                                        'bg-red-800 text-red-200'
                                    }`}>
                                        {job.status}
                                    </span>
                                </td>
                                <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-300">{job.cost}</td>
                                <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-400">{new Date(job.created_at).toLocaleString()}</td>
                            </tr>
                        ))}
                    </tbody>
                </table>
            </div>
        </div>
    );
};

// components/user/UserDashboard.tsx
const UserDashboard: React.FC = () => {
    const [activeTab, setActiveTab] = useState<'generator' | 'keys' | 'profile' | 'jobs'>('generator');

    const renderTabContent = () => {
        switch (activeTab) {
            case 'generator': return <ImageGenerator />;
            case 'keys': return <ApiKeyManager />;
            case 'profile': return <UserProfileDisplay />;
            case 'jobs': return <JobHistory />;
            default: return null;
        }
    };

    const TabButton = ({ tab, label }: { tab: 'generator' | 'keys' | 'profile' | 'jobs'; label: string }) => (
        <button
            onClick={() => setActiveTab(tab)}
            className={`px-4 py-2 text-sm font-medium rounded-md transition-colors ${
                activeTab === tab 
                ? 'bg-indigo-600 text-white' 
                : 'text-gray-300 hover:bg-gray-700'
            }`}
        >
            {label}
        </button>
    );

    return (
        <div className="space-y-6">
            <div className="flex space-x-2 p-2 bg-gray-800 rounded-lg">
                <TabButton tab="generator" label="Image Generator" />
                <TabButton tab="keys" label="API Keys" />
                <TabButton tab="profile" label="Profile & Subscription" />
                <TabButton tab="jobs" label="Job History" />
            </div>
            <div className="p-6 bg-gray-800 rounded-lg shadow-inner">
                {renderTabContent()}
            </div>
        </div>
    );
};

// components/admin/PlanManager.tsx
const PlanManager: React.FC = () => {
    const { jwt } = useAuth();
    const [plans, setPlans] = useState<Plan[]>([]);
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError] = useState('');
    const [isModalOpen, setIsModalOpen] = useState(false);
    const [currentPlan, setCurrentPlan] = useState<Plan>({
      id: '', name: '', price: 0, monthlyGenerations: 0, monthlyTokens: 0, allowedParams: [],
      fixedParams: {}, rateLimits: { requestsPerMinute: 0, requestsPerHour: 0, requestsPerDay: 0 },
    });
    const [isEditing, setIsEditing] = useState(false);

    const fetchPlans = useCallback(async () => {
        if (!jwt) return;
        setIsLoading(true);
        setError('');
        try {
            const fetchedPlans = await apiService.getPlans(jwt);
            setPlans(fetchedPlans);
        } catch (err) {
            setError(err instanceof Error ? err.message : 'Failed to fetch plans');
        } finally {
            setIsLoading(false);
        }
    }, [jwt]);

    useEffect(() => {
        fetchPlans();
    }, [fetchPlans]);

    const openCreateModal = () => {
        setCurrentPlan({
          id: '', name: '', price: 0, monthlyGenerations: 0, monthlyTokens: 0, allowedParams: [],
          fixedParams: {}, rateLimits: { requestsPerMinute: 0, requestsPerHour: 0, requestsPerDay: 0 },
        });
        setIsEditing(false);
        setIsModalOpen(true);
    };

    const openEditModal = (plan: Plan) => {
        setCurrentPlan(plan);
        setIsEditing(true);
        setIsModalOpen(true);
    };

    const handleFormChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        const { name, value } = e.target;
        if (name.startsWith('rateLimits.')) {
            const key = name.split('.')[1];
            setCurrentPlan(prev => ({
                ...prev,
                rateLimits: { ...prev.rateLimits, [key]: Number(value) }
            }));
        } else if (name === 'allowedParams' || name === 'fixedParams') {
            try {
                if (name === 'fixedParams') {
                    const parsedValue = JSON.parse(value);
                     setCurrentPlan(prev => ({ ...prev, [name]: parsedValue }));
                } else {
                     setCurrentPlan(prev => ({ ...prev, [name]: value.split(',').map(s => s.trim()) }));
                }
            } catch (e) {
                console.error("JSON parsing error", e)
            }
        } else {
            setCurrentPlan(prev => ({
                ...prev,
                [name]: (name === 'price' || name === 'monthlyGenerations' || name === 'monthlyTokens') ? Number(value) : value,
            }));
        }
    };
    
    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        if (!jwt) return;
        setIsLoading(true);
        setError('');
        try {
            if (isEditing) {
                await apiService.updatePlan(jwt, currentPlan.id, currentPlan);
            } else {
                await apiService.createPlan(jwt, currentPlan);
            }
            setIsModalOpen(false);
            await fetchPlans();
        } catch (err) {
            setError(err instanceof Error ? err.message : `Failed to ${isEditing ? 'update' : 'create'} plan`);
        } finally {
            setIsLoading(false);
        }
    };
    
    const handleDelete = async (planId: string) => {
        if (!jwt || !window.confirm(`Are you sure you want to delete plan ${planId}?`)) return;
        setIsLoading(true);
        try {
            await apiService.deletePlan(jwt, planId);
            await fetchPlans();
        } catch (err) {
             setError(err instanceof Error ? err.message : 'Failed to delete plan');
        } finally {
            setIsLoading(false);
        }
    };

    return (
        <div className="space-y-6">
            <div className="flex justify-between items-center">
                <h3 className="text-xl font-semibold">Subscription Plans</h3>
                <button onClick={openCreateModal} className="px-4 py-2 font-bold text-white bg-indigo-600 rounded-md hover:bg-indigo-700">
                    Create New Plan
                </button>
            </div>

            {error && <p className="p-3 bg-red-900/50 text-red-300 border border-red-500 rounded-md">{error}</p>}
            {isLoading && !plans.length && <p>Loading plans...</p>}
            
            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
                {plans.map(plan => (
                    <div key={plan.id} className="bg-gray-700 p-4 rounded-lg space-y-2">
                        <h4 className="font-bold text-lg text-indigo-300">{plan.name} <span className="text-sm font-mono text-gray-400">({plan.id})</span></h4>
                        <p>Price: ${plan.price}</p>
                        <p>Generations/Month: {plan.monthlyGenerations}</p>
                        <p>Tokens/Month: {plan.monthlyTokens}</p>
                        <div className="flex space-x-2 pt-2">
                            <button onClick={() => openEditModal(plan)} className="flex-1 text-sm px-3 py-1 bg-gray-600 hover:bg-gray-500 rounded">Edit</button>
                            <button onClick={() => handleDelete(plan.id)} className="flex-1 text-sm px-3 py-1 bg-red-800 hover:bg-red-700 rounded">Delete</button>
                        </div>
                    </div>
                ))}
            </div>

            {isModalOpen && (
                <div className="fixed inset-0 bg-black/60 flex items-center justify-center p-4">
                    <div className="bg-gray-800 p-6 rounded-lg w-full max-w-2xl max-h-[90vh] overflow-y-auto">
                        <h4 className="text-xl font-bold mb-4">{isEditing ? 'Edit Plan' : 'Create Plan'}</h4>
                        <form onSubmit={handleSubmit} className="space-y-4">
                            <div className="grid grid-cols-2 gap-4">
                                <div><label className="block text-sm">ID</label><input type="text" name="id" value={currentPlan.id} onChange={handleFormChange} disabled={isEditing} className="w-full bg-gray-700 p-2 rounded" /></div>
                                <div><label className="block text-sm">Name</label><input type="text" name="name" value={currentPlan.name} onChange={handleFormChange} className="w-full bg-gray-700 p-2 rounded" /></div>
                                <div><label className="block text-sm">Price</label><input type="number" name="price" value={currentPlan.price} onChange={handleFormChange} className="w-full bg-gray-700 p-2 rounded" /></div>
                                <div><label className="block text-sm">Monthly Generations</label><input type="number" name="monthlyGenerations" value={currentPlan.monthlyGenerations} onChange={handleFormChange} className="w-full bg-gray-700 p-2 rounded" /></div>
                                <div><label className="block text-sm">Monthly Tokens</label><input type="number" name="monthlyTokens" value={currentPlan.monthlyTokens} onChange={handleFormChange} className="w-full bg-gray-700 p-2 rounded" /></div>
                            </div>
                            <div>
                                <label className="block text-sm">Allowed Params (comma-separated)</label>
                                <textarea name="allowedParams" value={Array.isArray(currentPlan.allowedParams) ? currentPlan.allowedParams.join(', ') : ''} onChange={handleFormChange} className="w-full bg-gray-700 p-2 rounded font-mono" rows={2} />
                            </div>
                            <div>
                                <label className="block text-sm">Fixed Params (JSON)</label>
                                <textarea name="fixedParams" value={JSON.stringify(currentPlan.fixedParams, null, 2)} onChange={handleFormChange} className="w-full bg-gray-700 p-2 rounded font-mono" rows={3} />
                            </div>
                             <div>
                                <label className="block text-sm font-bold">Rate Limits</label>
                                <div className="grid grid-cols-3 gap-2">
                                    <input type="number" name="rateLimits.requestsPerMinute" value={currentPlan.rateLimits.requestsPerMinute} onChange={handleFormChange} placeholder="Per Minute" className="w-full bg-gray-700 p-2 rounded"/>
                                    <input type="number" name="rateLimits.requestsPerHour" value={currentPlan.rateLimits.requestsPerHour} onChange={handleFormChange} placeholder="Per Hour" className="w-full bg-gray-700 p-2 rounded"/>
                                    <input type="number" name="rateLimits.requestsPerDay" value={currentPlan.rateLimits.requestsPerDay} onChange={handleFormChange} placeholder="Per Day" className="w-full bg-gray-700 p-2 rounded"/>
                                </div>
                            </div>
                            <div className="flex justify-end space-x-4 pt-4">
                                <button type="button" onClick={() => setIsModalOpen(false)} className="px-4 py-2 bg-gray-600 hover:bg-gray-500 rounded">Cancel</button>
                                <button type="submit" disabled={isLoading} className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 rounded disabled:bg-gray-500">{isLoading ? 'Saving...' : 'Save Plan'}</button>
                            </div>
                        </form>
                    </div>
                </div>
            )}
        </div>
    );
};

// components/admin/AdminDashboard.tsx
const AdminDashboard: React.FC = () => {
    return (
        <div>
            <h2 className="text-3xl font-bold mb-6 text-indigo-400">Admin Panel</h2>
            <div className="p-6 bg-gray-800 rounded-lg shadow-inner">
                <PlanManager />
            </div>
        </div>
    );
};

// --- APP ---
const AppContent: React.FC = () => {
    const { jwt, user, setUser } = useAuth();
    const [view, setView] = useState<'user' | 'admin'>('user');

    useEffect(() => {
        const fetchProfile = async () => {
            if (jwt && !user) {
                try {
                    const profile = await apiService.getProfile(jwt);
                    setUser(profile);
                } catch (error) {
                    console.error("Failed to fetch profile", error);
                    // Handle error, maybe logout
                }
            }
        };
        fetchProfile();
    }, [jwt, user, setUser]);


    if (!jwt) {
        return <LoginPage />;
    }

    return (
        <div className="min-h-screen bg-gray-900 text-gray-100 font-sans">
            <header className="bg-gray-800 shadow-md">
                <div className="container mx-auto px-6 py-4 flex justify-between items-center">
                    <h1 className="text-2xl font-bold text-indigo-400">Jitome API Frontend</h1>
                    <nav className="flex items-center space-x-4">
                        {user?.is_admin && (
                             <button
                                onClick={() => setView(view === 'user' ? 'admin' : 'user')}
                                className="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 rounded-md transition-colors"
                            >
                                Switch to {view === 'user' ? 'Admin' : 'User'} View
                            </button>
                        )}
                         <span className="text-gray-400">Welcome, {user?.username}</span>
                    </nav>
                </div>
            </header>
            <main className="container mx-auto p-6">
                {view === 'user' ? <UserDashboard /> : <AdminDashboard />}
            </main>
        </div>
    );
};

const App: React.FC = () => {
    return (
        <AuthProvider>
            <AppContent />
        </AuthProvider>
    );
};

// --- RENDER ---
const rootElement = document.getElementById('root');
if (!rootElement) {
  throw new Error("Could not find root element to mount to");
}

const root = ReactDOM.createRoot(rootElement);
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);