/**
 * Unified Video Upload and Mint Script
 * 
 * This script demonstrates the one-step method to upload a video and mint an NFT
 * when processing is complete.
 * 
 * Usage:
 * 1. Create a .env file and set the following environment variables:
 *    - PRIVATE_KEY: Private key of the NFT holder
 *    - API_KEY: GoodTake API key (optional)
 * 
 * 2. Prepare a test video file and place it in scripts/assets/ directory
 * 
 * 3. Run the script:
 *    npm run upload-and-mint
 *    or
 *    yarn upload-and-mint
 */

import { GoTakeSDK, NetworkId, VideoStatus } from "../src";
import * as dotenv from 'dotenv';
import { ethers } from 'ethers';
import * as fs from 'fs';
import * as path from 'path';
import { Blob } from 'fetch-blob';
import File from 'fetch-blob/file';

dotenv.config();

// Utility function: Convert file system file to browser File object
function createFileFromPath(filePath: string): File {
    const fileName = path.basename(filePath);
    const fileBuffer = fs.readFileSync(filePath);
    const fileBlob = new Blob([fileBuffer]);
    return new File([fileBlob], fileName, { type: getMimeType(fileName) });
}

// Utility function: Get MIME type based on file extension
function getMimeType(fileName: string): string {
    const ext = fileName.split('.').pop()?.toLowerCase();
    const mimeTypes: Record<string, string> = {
        'mp4': 'video/mp4',
        'mov': 'video/quicktime',
        'avi': 'video/x-msvideo',
        'webm': 'video/webm'
    };
    return mimeTypes[ext || ''] || 'application/octet-stream';
}

async function main() {
    // Check required environment variables
    if (!process.env.PRIVATE_KEY) {
        throw new Error("PRIVATE_KEY is not defined in environment variables. Please set it in your .env file");
    }

    const videoFilePath = path.join(__dirname, 'assets', 'sample-video.mp4');
    if (!fs.existsSync(videoFilePath)) {
        throw new Error(`Test video file not found: ${videoFilePath}`);
    }

    try {
        console.log("=== GoodTake One-Step Upload and Mint Demo ===");

        // Create Provider and Signer
        const rpcUrl = "https://sepolia.base.org";
        const ethersProvider = new ethers.providers.JsonRpcProvider(rpcUrl);
        const ethersSigner = new ethers.Wallet(process.env.PRIVATE_KEY, ethersProvider);
        const userAddress = await ethersSigner.getAddress();

        console.log(`Using address: ${userAddress}`);

        // Initialize SDK
        const sdk = new GoTakeSDK({
            network: NetworkId.BASE_SEPOLIA,
            provider: ethersProvider,
            signer: ethersSigner,
            apiEndpoint: process.env.API_ENDPOINT || 'https://api.goodtake.io',
            apiKey: process.env.API_KEY
        });
        console.log("SDK initialized successfully");

        // Step 1: Check and create TBA if needed (done automatically by the unified method)
        console.log("\nChecking TBA account...");

        // Step 2: Prepare video file
        console.log("\nPreparing video file...");
        const videoFile = createFileFromPath(videoFilePath);
        console.log(`Video file: ${videoFile.name} (${videoFile.size} bytes)`);

        const videoMetadata = {
            title: "One-Step Upload Demo",
            description: "This video was uploaded and minted in one step",
            tags: ["demo", "sdk", "one-step"],
            creator: userAddress
        };

        // Step 3: Use the unified method to upload and mint
        console.log("\n=== Starting Unified Upload and Mint Process ===");
        console.log("This will automatically upload, monitor, and mint when ready");

        // Track process completion
        let processCompleted = false;

        // Use the unified method
        const videoId = await sdk.uploadAndMintWhenReady(
            videoFile,
            videoMetadata,
            {
                statusCallback: (status) => {
                    console.log(`Status update: ${status.status}, Progress: ${status.progress || 'unknown'}%`);

                    if (status.status === VideoStatus.COMPLETED) {
                        console.log("\n=== Process Completed Successfully ===");
                        console.log(`Video ID: ${videoId}`);
                        if (status.mintInfo) {
                            console.log(`NFT Token ID: ${status.mintInfo.tokenId}`);
                            console.log(`NFT Transaction: ${status.mintInfo.transactionHash}`);
                        }
                        if (status.assetInfo?.playbackUrl) {
                            console.log(`Playback URL: ${status.assetInfo.playbackUrl}`);
                        }
                        processCompleted = true;
                    } else if (status.status === VideoStatus.ERROR) {
                        console.error(`Error: ${status.error?.message || 'Unknown error'}`);
                        processCompleted = true;
                    }
                },
                autoMint: true // Automatically mint when video is ready
            }
        );

        console.log(`Process started! Video ID: ${videoId}`);
        console.log("The process will continue in the background.");
        console.log("Status updates will be displayed via the callback.");

        // Wait for process to complete or timeout after 10 minutes
        const timeout = 10 * 60 * 1000; // 10 minutes
        const startTime = Date.now();

        while (!processCompleted && (Date.now() - startTime < timeout)) {
            await new Promise(resolve => setTimeout(resolve, 5000)); // Check every 5 seconds

            // Check status directly if needed
            if (!processCompleted && (Date.now() - startTime) % 30000 < 5000) { // Every 30 seconds
                const status = await sdk.getVideoStatus(videoId);
                console.log(`Current status: ${status.status}`);
            }
        }

        if (!processCompleted) {
            console.log("\nTimeout reached but process is still running in the background.");
            console.log(`You can check the status later using the video ID: ${videoId}`);
        }

    } catch (error) {
        console.error("Error during upload and mint process:");
        console.error(error);
        process.exitCode = 1;
    }
}

main().catch(error => {
    console.error("Error executing script:");
    console.error(error);
    process.exitCode = 1;
}); 