'use client';

import { IVtuber } from "@/lib/vtubers";
import { IStream } from "@/lib/streams";
import { useSearchParams } from 'next/navigation';
import React, { useContext, useState, useEffect } from 'react';
import { UppyContext } from 'app/uppy';
import AwsS3 from '@uppy/aws-s3';
import RemoteSources from '@uppy/remote-sources';
import { LoginButton, useAuth } from '@/components/auth';
import { Dashboard } from '@uppy/react';
import styles from '@/assets/styles/fp.module.css'
import { projektMelodyEpoch } from "@/lib/constants";
import add from "date-fns/add";
import sub from "date-fns/sub";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheckCircle, faEraser, faPaperPlane, faSpinner, faX, faXmark } from "@fortawesome/free-solid-svg-icons";
import { useForm, useFieldArray, ValidationMode } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
import qs from 'qs';
import { toast } from "react-toastify";
import { ErrorMessage } from "@hookform/error-message"
import Uppy from '@uppy/core';
import { companionUrl } from '@/lib/constants';



interface IUploadFormProps {
    vtubers: IVtuber[];
}

interface IValidationResults {
    valid: boolean;
    issues: string[] | null;
}

interface IFormSchema extends Yup.InferType<typeof validationSchema> { };


const validationSchema = Yup.object().shape({
    vtuber: Yup.number()
        .required('VTuber is required'),
    streamCuid: Yup.string().optional(),
    date: Yup.date()
        .typeError('Invalid date') // https://stackoverflow.com/a/72985532/1004931
        .min(sub(projektMelodyEpoch, { days: 1 }), 'Date must be after February 7 2020')
        .max(add(new Date(), { days: 1 }), 'Date cannot be in the future')
        .required('Date is required'),
    notes: Yup.string().optional(),
    attribution: Yup.boolean().optional(),
    files: Yup.array()
        .of(
            Yup.object().shape({
                key: Yup.string().required('key is required'),
                uploadId: Yup.string().required('uploadId is required')
            }),
        )
        .min(1, 'At least one file is required'),
});



export default function UploadForm({ vtubers }: IUploadFormProps) {
    const searchParams = useSearchParams();
    const cuid = searchParams.get('cuid');

    const { authData } = useAuth();

    const uppy = new Uppy(
            {
              autoProceed: true,
              debug: true,
              logger: {
                debug: console.info,
                warn: console.log,
                error: console.error
              },
            }
          )
          .use(RemoteSources, {
            companionUrl,
            sources: [
                'GoogleDrive',
                'Dropbox',
                'Url'
            ]
          })
          .use(AwsS3, {
            companionUrl,
            shouldUseMultipart: true,
            abortMultipartUpload: () => {}, // @see https://github.com/transloadit/uppy/issues/1197#issuecomment-491756118
            companionHeaders: {
              'authorization': `Bearer ${authData?.accessToken}`
            }
          })



    const formOptions = {
        resolver: yupResolver(validationSchema),
        mode: 'onChange' as keyof ValidationMode,
    };
    const {
        register,
        handleSubmit,
        setError,
        clearErrors,
        formState: {
            errors,
            isValid,
            isSubmitted,
            isSubmitSuccessful,
            isSubmitting
        },
        setValue,
        watch,
        reset
    } = useForm(formOptions);


    // useEffect(() => {
    //     if (!cuid) return;
    //     (async () => {
    //         console.log('query')
    //         const query = qs.stringify({
    //             filters: {
    //                 cuid: {
    //                     '$eq': cuid
    //                 }
    //             }
    //         });
    //         const res = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/streams?${query}`);
    //         if (!res.ok) return;
    //         const matchingStream = (await res.json()).data as IStream;
    //         console.log(matchingStream);
    //         setValue('vtuber', matchingStream.attributes.vtuber.data.id);
    //     })();
    // }, [cuid]);

    // setValue('streamCuid', cuid||'');
    const files = watch('files');



    async function createUSC(data: IFormSchema) {
        try {
            const res = await fetch(`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/user-submitted-contents/createFromUppy`, {
                method: 'POST',
                headers: {
                    'authorization': `Bearer ${authData?.accessToken}`,
                    'content-type': 'application/json',
                    'accept': 'application/json'
                },
                body: JSON.stringify({
                    data: {
                        files: data.files,
                        attribution: data.attribution,
                        notes: data.notes,
                        vtuber: data.vtuber,
                        date: data.date,
                        streamCuid: cuid
                    }
                })
            });

            if (!res.ok) {
                console.error('failed to fetch /api/user-submitted-contents/createFromUppy');
                const body = await res.json();
                const error = body.error;
                toast.error(`${error.type} ${error.message}`, { theme: 'dark' });

                setError('root.serverError', {
                    type: error.type,
                    message: error.message
                })
            }
        } catch (e) {
            if (e instanceof Error) {
                toast.error(`${e.message}`, { theme: 'dark' });
                setError('root.serverError', {
                    type: "remote",
                    message: e.message,
                });
            } else {
                toast.error(`Something went wrong. Please try again.`, { theme: 'dark' });
                setError('root.serverError', {
                    type: 'remote',
                    message: 'Something went wrong. Please try again.'
                })
            }
        }
    }


    uppy.on('complete', async (result: any) => {
        for (const s of result.successful) {
            if (!s?.s3Multipart) {
                const m = 'file was missing s3Multipart'
                toast.error(`${m}`, { theme: 'dark' });
                setError('root.serverError', {
                    type: 'remote',
                    message: m
                })
                throw new Error(m)
            }
        }
        console.log('uppy complete! ')
        console.log(result)
        toast.success(`upload complete`);
        let files = result.successful.map((f: any) => ({ key: f.s3Multipart.key, uploadId: f.s3Multipart.uploadId }));
        setValue('files', files);
    });


    return (
        <>

            <div className='section'>
                <h2 className='title is-2'>Upload VOD</h2>

                <p className="mb-5"><i>Together we can archive all lewdtuber livestreams!</i></p>

                {(!authData?.accessToken)
                    ?
                    <>
                        <aside className='notification is-danger'><p>Please log in to upload VODs</p></aside>
                        <LoginButton />
                    </>
                    : (



                        <div className='columns is-multiline'>
                            <form id="vod-details" onSubmit={handleSubmit(createUSC)}>


                                {(!isSubmitSuccessful) && <div className='column is-full'>
                                    <section className="hero is-info mb-3">
                                        <div className="hero-body">
                                            <p className="title">
                                                Step 1
                                            </p>
                                            <p className="subtitle">
                                                Upload the file
                                            </p>
                                        </div>
                                    </section>
                                    <section className="section mb-5">
                                        <Dashboard
                                            uppy={uppy}
                                            theme='dark'
                                            proudlyDisplayPoweredByUppy={true}
                                            showProgressDetails={true}
                                        />

                                        {/* 
                                            Here is how we upload the files to the server.
                                            From uppy, we get a list of files.
                                            we add the files to a hidden input box.
                                            the input box is part of the form which gets POSTed.
                                        */}
                                        <input
                                            required
                                            hidden={true}
                                            style={{ display: 'block' }}
                                            className="input" type="text"
                                            {...register('files')}
                                        ></input>

                                        <button className="button" onClick={() => { setValue('files', [
                                            {
                                                "key": "4b4063a2-6b57-48f1-8565-a12ddce473e9-E1tB0KoUcAYJTni.jpg",
                                                "uploadId": "4_z7d53875ff1c32a1983d30b18_f2129582707239923_d20240708_m003328_c000_v0001086_t0006_u01720398808368"
                                            }
                                        ]); }}>(Debug) Add a list of files</button>

               
                                        {errors.files && <p className="help is-danger">{errors.files.message?.toString()}</p>}

                                    </section>
                                </div>}

                                {(!isSubmitSuccessful) && <div className='column is-full '>
                                    {/* {(!cuid) && <aside className='notification is-info'>Hint: Some of these fields are filled out automatically when uploading from a <Link href="/streams">stream</Link> page.</aside>} */}

                                    <section className="hero is-info mb-3">
                                        <div className="hero-body">
                                            <p className="title">
                                                Step 2
                                            </p>
                                            <p className="subtitle">
                                                Tell us about the VOD
                                            </p>
                                        </div>
                                    </section>

                                    <section className="section">



                                        {/* <input
                                            required
                                            // hidden={false}
                                            // style={{ display: 'none' }}
                                            className="input" type="text"
                                            {...register('streamCuid')}
                                        ></input> */}


                                        <div className="field">
                                            <label className="label">VTuber</label>
                                            <div className="select">
                                                <select
                                                    required
                                                    // value={vtuber}
                                                    // onChange={(evt) => setVtuber(parseInt(evt.target.value))}
                                                    {...register('vtuber')}
                                                >
                                                    {vtubers.map((vtuber: IVtuber) => (
                                                        <option key={vtuber.id} value={vtuber.id}>{vtuber.attributes.displayName}</option>
                                                    ))}
                                                </select>
                                            </div>
                                            <p className="help is-info">Choose the VTuber this VOD belongs to. (More VTubers will be added when storage/bandwidth funding is secured.)</p>
                                            {errors.vtuber && <p className="help is-danger">vtuber error</p>}

                                        </div>

                                        <div className="field">
                                            <label className="label">Stream Date</label>
                                            <input
                                                required
                                                className="input" type="date"
                                                {...register('date')}
                                            // onChange={(evt) => setDate(evt.target.value)}
                                            ></input>
                                            <p className="help is-info">The date when the VOD was originally streamed.</p>
                                            {errors.date && <p className="help is-danger">{errors.date.message?.toString()}</p>}

                                        </div>

                                        <div className="field">
                                            <label className="label">Notes</label>
                                            <textarea
                                                className="textarea"
                                                placeholder="e.g. Missing first 10 minutes of stream"
                                                // onChange={(evt) => setNote(evt.target.value)}
                                                {...register('notes')}
                                            ></textarea>
                                            <p className="help is-info">If there are any issues with the VOD, put a note here. If there are no VOD issues, leave this field blank.</p>
                                        </div>

                                        <div className="field">
                                            <label className="label">Attribution</label>
                                            <label className="checkbox">
                                                <input
                                                    type="checkbox"
                                                    // onChange={(evt) => setAttribution(evt.target.checked)}
                                                    {...register('attribution')}
                                                />
                                                <span className={`ml-2 ${styles.noselect}`}>Credit {authData.user?.username} for the upload.</span>
                                                <p className="help is-info">Check this box if you want your username displayed on the website. Thank you for uploading!</p>
                                            </label>
                                        </div>

                                    </section>

                                </div>}


                                <div className="column is-full">
                                    <section className="hero is-info">
                                        <div className="hero-body">
                                            <p className="title">
                                                Step 3
                                            </p>
                                            <p className="subtitle">
                                                Send the form
                                            </p>
                                        </div>
                                    </section>
                                    <section className="section">




                                        {errors.root?.serverError && (
                                            <div className="notification">
                                                <button className="delete" onClick={() => clearErrors()}></button>
                                                <ErrorMessage name="root" errors={errors} ></ErrorMessage>
                                          </div>
                                        )}



                                        {!isSubmitSuccessful && (
                                            <button className="button is-primary is-large mt-5">
                                                <span className="icon is-small">
                                                    <FontAwesomeIcon icon={faPaperPlane}></FontAwesomeIcon>
                                                </span>
                                                <span>Send</span>
                                            </button>
                                        )}

                                        {isSubmitting && (
                                            <p>
                                                <FontAwesomeIcon className="mt-5 fa-spin-pulse" icon={faSpinner} ></FontAwesomeIcon>
                                            </p>
                                        )}
                                        {isSubmitSuccessful && (
                                            <>
                                                <aside className="notification mt-5 is-success">Thank you for uploading! A moderator will review the VOD before being published.</aside>
                                                <button onClick={() => {
                                                    reset(); // reset form
                                                    const files = uppy.getFiles() 
                                                    for (const file of files) { 
                                                        uppy.removeFile(file.id); // reset uppy
                                                    }
                                                }} className="button is-primary">
                                                    <span className="icon is-small">
                                                        <FontAwesomeIcon icon={faEraser}></FontAwesomeIcon>
                                                    </span>
                                                    <span>Reset form</span>
                                                </button>
                                            </>
                                        )}



                                    </section>
                                </div>

                            </form>
                        </div>


                    )
                }

            </div>

        </>
    )

}
