import React, { useState } from 'react';
import {
    Alert,
    Field,
    Form,
    PageHeader,
    Select,
    Tooltip,
} from '@theorchard/suite-components';
import type { TwoLineOption } from '../types';
import type { AccountForTransfer } from 'src/apollo/queries/account';

type LoadOptions = (
    term?: string
) => Promise<{ data: TwoLineOption[]; totalCount: number }>;

interface DetailsStepProps {
    fromAccount: AccountForTransfer | undefined;
    toAccount: AccountForTransfer | undefined;
    projectId: string | undefined;
    contractId: string | undefined;
    toSubaccountId: string | undefined;
    toSubaccountOptions: TwoLineOption[];
    fromSubaccountId: string | undefined;
    fromSubaccountOptions: TwoLineOption[];
    contractOptions: TwoLineOption[];
    onLoadFromOptions: LoadOptions;
    onLoadToOptions: LoadOptions;
    onLoadProjectOptions: LoadOptions;
    onFromAccountChange: (item: TwoLineOption | undefined) => void;
    onFromSubaccountChange: (subaccountId: string | undefined) => void;
    onToAccountChange: (item: TwoLineOption | undefined) => void;
    onProjectChange: (project: TwoLineOption | undefined) => void;
    onContractChange: (contractId: string | undefined) => void;
    onToSubaccountChange: (subaccountId: string | undefined) => void;
}

const DetailsStep: React.FC<DetailsStepProps> = ({
    fromAccount,
    toAccount,
    projectId,
    contractId,
    toSubaccountId,
    toSubaccountOptions,
    fromSubaccountId,
    fromSubaccountOptions,
    contractOptions,
    onLoadFromOptions,
    onLoadToOptions,
    onLoadProjectOptions,
    onFromAccountChange,
    onFromSubaccountChange,
    onToAccountChange,
    onProjectChange,
    onContractChange,
    onToSubaccountChange,
}) => {
    const fromAccountId = fromAccount?.accountId;
    const toAccountId = toAccount?.accountId;
    // The project picker is type-to-search (the exact id/code lookups need a
    // term), so there is no preloaded option list to read the selection back
    // from. Remember the picked option to keep it displayed.
    const [pickedProject, setPickedProject] = useState<
        TwoLineOption | undefined
    >(undefined);
    const fromAndProjectSelected = !!(fromAccountId && projectId);
    // All three selectors are filled. This only gates the timing-info banner;
    // it is NOT the "can proceed" check, which lives in CreateTransferForm and
    // also requires the project's product/track tree to have resolved.
    const allSelectorsChosen = !!(fromAccountId && toAccountId && projectId);
    // The origin subaccount selector shows only when the account has
    // subaccounts (like the destination side); when it does, the project
    // picker waits for one to be chosen.
    const fromSubaccountRequired = fromSubaccountOptions.length > 0;
    const projectDisabled =
        !fromAccountId || (fromSubaccountRequired && !fromSubaccountId);

    const fromAccountOption: TwoLineOption | undefined = fromAccount
        ? {
              label: fromAccount.accountName,
              value: fromAccount.accountId,
              subtitle: String(fromAccount.vendor.vendorId),
          }
        : undefined;

    const toAccountOption: TwoLineOption | undefined = toAccount
        ? {
              label: toAccount.accountName,
              value: toAccount.accountId,
              subtitle: String(toAccount.vendor.vendorId),
          }
        : undefined;

    const singleContract = contractOptions.length === 1;

    const contractSelect = (
        <Select
            name="contract"
            options={contractOptions}
            selectedValue={
                contractOptions.find(o => o.value === contractId) ?? undefined
            }
            onChange={(item: TwoLineOption | undefined) =>
                onContractChange(item?.value ?? undefined)
            }
            placeholder="Select Contract"
            filterPlaceholder="Search contract"
            showSelectedSubtitle
            disabled={singleContract}
            portalElement={document.body}
        />
    );

    return (
        <>
            <div className="CreateTransferForm-header">
                <PageHeader.Title className="CreateTransferForm-title">
                    Set up what to Transfer
                </PageHeader.Title>
                <p className="CreateTransferForm-subtitle">
                    Select the original account and the derived account with the
                    specific contract of destination
                </p>
            </div>
            <div className="CreateTransferForm-body">
                <Form>
                    <Form.Group>
                        <Field controlId="fromAccount" labelText="From Account">
                            <Select
                                name="fromAccount"
                                onLoadOptions={onLoadFromOptions}
                                selectedValue={fromAccountOption}
                                onChange={(item: TwoLineOption | undefined) =>
                                    onFromAccountChange(item)
                                }
                                placeholder="Select Account"
                                filterPlaceholder="Search account"
                                showSelectedSubtitle
                                portalElement={document.body}
                            />
                        </Field>
                    </Form.Group>

                    {fromAccountId && fromSubaccountRequired && (
                        <Form.Group>
                            <Field
                                controlId="fromSubaccount"
                                labelText="From Subaccount"
                            >
                                <Select
                                    // Remount on account change so a stale menu
                                    // can't linger after the account is switched.
                                    key={fromAccountId ?? 'no-account'}
                                    name="fromSubaccount"
                                    options={fromSubaccountOptions}
                                    selectedValue={
                                        fromSubaccountOptions.find(
                                            o => o.value === fromSubaccountId
                                        ) ?? undefined
                                    }
                                    onChange={(
                                        item: TwoLineOption | undefined
                                    ) =>
                                        onFromSubaccountChange(
                                            item?.value ?? undefined
                                        )
                                    }
                                    placeholder="Select Subaccount"
                                    showSelectedSubtitle
                                    portalElement={document.body}
                                />
                            </Field>
                        </Form.Group>
                    )}

                    <Form.Group>
                        <Field controlId="project" labelText="Project">
                            <Select
                                // Remount when the account or subaccount changes
                                // so a stale, portaled project menu can't linger
                                // open, and the scoped search resets (the suite
                                // Select keeps its open menu when disabled).
                                key={`${fromAccountId ?? 'no-account'}-${
                                    fromSubaccountId ?? 'no-subaccount'
                                }`}
                                name="project"
                                onLoadOptions={onLoadProjectOptions}
                                selectedValue={
                                    projectId ? pickedProject : undefined
                                }
                                onChange={(item: TwoLineOption | undefined) => {
                                    setPickedProject(item);
                                    onProjectChange(item);
                                }}
                                placeholder="Select Project"
                                filterPlaceholder="Search project"
                                disabled={projectDisabled}
                                showSelectedSubtitle
                                portalElement={document.body}
                            />
                        </Field>
                    </Form.Group>

                    {fromAndProjectSelected && (
                        <>
                            <Form.Group>
                                <Field
                                    controlId="toAccount"
                                    labelText="To Account"
                                >
                                    <Select
                                        name="toAccount"
                                        onLoadOptions={onLoadToOptions}
                                        selectedValue={toAccountOption}
                                        onChange={(
                                            item: TwoLineOption | undefined
                                        ) => onToAccountChange(item)}
                                        placeholder="Select Account"
                                        filterPlaceholder="Search account"
                                        showSelectedSubtitle
                                        portalElement={document.body}
                                    />
                                </Field>
                            </Form.Group>

                            {toAccountId && toSubaccountOptions.length > 0 && (
                                <Form.Group>
                                    <Field
                                        controlId="toSubaccount"
                                        labelText="To Subaccount"
                                    >
                                        <Select
                                            name="toSubaccount"
                                            options={toSubaccountOptions}
                                            selectedValue={
                                                toSubaccountOptions.find(
                                                    o =>
                                                        o.value ===
                                                        toSubaccountId
                                                ) ?? undefined
                                            }
                                            onChange={(
                                                item: TwoLineOption | undefined
                                            ) =>
                                                onToSubaccountChange(
                                                    item?.value ?? undefined
                                                )
                                            }
                                            placeholder="Select Subaccount (optional)"
                                            showSelectedSubtitle
                                            portalElement={document.body}
                                        />
                                    </Field>
                                </Form.Group>
                            )}

                            {toAccountId && (
                                <Form.Group>
                                    <Field
                                        controlId="contract"
                                        labelText="Contract of Destination"
                                    >
                                        {singleContract ? (
                                            <Tooltip
                                                id="single-contract-tooltip"
                                                placement="top"
                                                message="This account has only one contract, so it's selected automatically."
                                            >
                                                <span
                                                    style={{
                                                        display: 'inline-block',
                                                        width: '100%',
                                                    }}
                                                >
                                                    {contractSelect}
                                                </span>
                                            </Tooltip>
                                        ) : (
                                            contractSelect
                                        )}
                                    </Field>
                                </Form.Group>
                            )}
                        </>
                    )}

                    {allSelectorsChosen && (
                        <Alert
                            className="CreateTransferForm-info"
                            variant="information"
                            title="Transfers take effect at the start of the next accounting run"
                            text={
                                <>
                                    <p>
                                        Because you cannot backdate a transfer,
                                        the accounting cutoff date is strictly
                                        locked to the end of the month prior to
                                        queuing.
                                    </p>
                                    <ul>
                                        <li>
                                            <strong>
                                                This Month&apos;s Run:
                                            </strong>{' '}
                                            Revenue processed this month will be
                                            paid to{' '}
                                            <strong>
                                                {fromAccount?.accountName}
                                            </strong>
                                            .
                                        </li>
                                        <li>
                                            <strong>
                                                Next Month&apos;s Run:
                                            </strong>{' '}
                                            The transfer executes, and
                                            subsequent revenue will be paid to{' '}
                                            <strong>
                                                {toAccount?.accountName}
                                            </strong>
                                            .
                                        </li>
                                    </ul>
                                </>
                            }
                        />
                    )}
                </Form>
            </div>
        </>
    );
};

export default DetailsStep;
