import React, { useState } from 'react';
import {
    Alert,
    Button,
    Card,
    Col,
    Container,
    Modal,
    Row,
    Tooltip,
    useToast,
} from '@theorchard/suite-components';
import { GlyphIcon } from '@theorchard/suite-icons';
import { useParams } from 'react-router-dom';
import { useDeleteContractMechanicalDeduction } from 'src/apollo/mutations/contract-mechanical-deductions';
import {
    CONTRACT_MECHANICAL_DEDUCTION_NO_CALCULATION_MSG,
    CONTRACT_MECHANICAL_DEDUCTIONS_PHYSICAL_ONLY_TERRITORIES,
    CONTRACT_MECH_DEDUCTION_MECHANICAL_TYPES,
    CONTRACT_MECH_DEDUCTION_TERRITORIES,
    deleteContractMechanicalDeductionDescription,
    deleteContractMechanicalDeductionTitle,
} from 'src/apollo/type-constants/contract';
import { ContractMechanicalDeductionSidecar } from 'src/components/contract-mechanical-deduction-edit/contract-mechanical-deduction-sidecar';
import type {
    AbacusContractMechDeductionMechanicalType,
    AbacusContractMechDeductionTerritory,
} from 'src/apollo/definitions/globalTypes';
import type { GetContractQuery } from 'src/apollo/queries/contract/__generated__/get-contract';
import RestrictedByAbacusProfileWrapper from 'src/components/restricted-by-abacus-profile-wrapper';

type AbacusContract = NonNullable<GetContractQuery['abacusContract']>;
type AbacusContractMechDeductions =
    AbacusContract['mechanicalDeductions'] extends (infer T)[] | null
        ? T
        : null;

export interface ContractMechanicalDeductionCardPropTypes {
    contractMechanicalDeduction: AbacusContractMechDeductions;
}

export const ContractMechanicalDeductionCard: React.FC<
    ContractMechanicalDeductionCardPropTypes
> = ({ contractMechanicalDeduction }) => {
    const { contractId } = useParams<{
        contractId: string;
    }>();
    const deleteContractMechanicalDeduction =
        useDeleteContractMechanicalDeduction(contractId);
    const [isDeleteModalOpen, setIsDeleteModalOpen] = useState<boolean>(false);
    const [isDeleting, setIsDeleting] = useState<boolean>(false);
    const [isSidecarOpen, setIsSidecarOpen] = useState<boolean>(false);
    const [error, setError] = useState<string | null>(null);
    const toast = useToast();
    const CONTRACT_MECHANICAL_DEDUCTION_TERRITORY =
        CONTRACT_MECH_DEDUCTION_TERRITORIES[
            contractMechanicalDeduction.territory
        ];
    const renderTerritoryWarning = (
        territory: AbacusContractMechDeductionTerritory
    ) => {
        if (
            CONTRACT_MECHANICAL_DEDUCTIONS_PHYSICAL_ONLY_TERRITORIES.includes(
                territory
            )
        ) {
            return (
                <Tooltip
                    id={territory}
                    testId="territoryWarningTooltip"
                    message={CONTRACT_MECHANICAL_DEDUCTION_NO_CALCULATION_MSG}
                >
                    <GlyphIcon
                        className="ContractMechanicalDeductions-mechanicalDeductionCard-territoryWarningIcon"
                        name="warning"
                        size={24}
                        data-testid="territoryWarningIcon"
                    />
                </Tooltip>
            );
        }
    };

    const generateConcatenatedMechanicalTypesDisplayText = (
        mechanicalTypes: AbacusContractMechDeductionMechanicalType[]
    ) => {
        return [...mechanicalTypes]
            .sort()
            .map(
                mechanicalType =>
                    CONTRACT_MECH_DEDUCTION_MECHANICAL_TYPES[mechanicalType]
            )
            .join(', ');
    };

    const handleDeleteContractMechanicalDeduction = async () => {
        try {
            await deleteContractMechanicalDeduction({
                variables: {
                    contractMechanicalDeductionId:
                        contractMechanicalDeduction?.contractMechanicalDeductionId,
                },
            });
            setIsDeleteModalOpen(false);
            toast('Mechanical deductions have been successfully updated.');
        } catch (e) {
            if (e instanceof Error)
                setError(
                    `Error ${e.message}, Failed to delete mechanical deduction.`
                );
            else
                setError(
                    `Error ${String(e)}, Failed to delete mechanical deduction.`
                );
        }
    };

    return (
        <Card data-testid="mechanicalDeductionCard">
            <Card.Body>
                <Card.Title>
                    <Container fluid>
                        <Row>
                            <Col className="ContractMechanicalDeductions-mechanicalDeductionCard-territoryCol">
                                <span
                                    className="ContractMechanicalDeductions-mechanicalDeductionCard-territoryText"
                                    data-testid="mechanicalDeductionTerritory"
                                >
                                    {renderTerritoryWarning(
                                        contractMechanicalDeduction.territory
                                    )}
                                    {
                                        CONTRACT_MECH_DEDUCTION_TERRITORIES[
                                            contractMechanicalDeduction
                                                .territory
                                        ]
                                    }
                                </span>
                            </Col>
                            <RestrictedByAbacusProfileWrapper>
                                <Col className="ContractMechanicalDeductions-mechanicalDeductionCard-buttonCol">
                                    <Button
                                        className="ContractMechanicalDeductions-mechanicalDeductionCard-editButton"
                                        variant="secondary"
                                        size="sm"
                                        data-testid="editButton"
                                        onClick={() => setIsSidecarOpen(true)}
                                    >
                                        <GlyphIcon name="edit" size={16} />
                                    </Button>
                                    <Button
                                        className="ContractMechanicalDeductions-mechanicalDeductionCard-deleteButton"
                                        variant="secondary"
                                        size="sm"
                                        data-testid="deleteButton"
                                        onClick={() =>
                                            setIsDeleteModalOpen(true)
                                        }
                                    >
                                        <GlyphIcon name="trash" size={16} />
                                    </Button>
                                    <Modal
                                        isOpen={isDeleteModalOpen}
                                        className="ContractDetail-deleteContractMechanicalDeductions-ReactModal"
                                        testId="deleteModal"
                                        title={deleteContractMechanicalDeductionTitle(
                                            CONTRACT_MECHANICAL_DEDUCTION_TERRITORY
                                        )}
                                        onRequestClose={() => {
                                            setIsDeleteModalOpen(false);
                                        }}
                                        onConfirm={async () => {
                                            setIsDeleting(true);
                                            await handleDeleteContractMechanicalDeduction();
                                        }}
                                        cancelTitle="No, Cancel"
                                        confirmTitle="Yes, Delete"
                                        hideCancelButton={isDeleting}
                                        confirmDisabled={isDeleting}
                                    >
                                        {error && (
                                            <>
                                                <Alert
                                                    variant="error"
                                                    text={error}
                                                    className="error-alert"
                                                />
                                            </>
                                        )}
                                        {deleteContractMechanicalDeductionDescription(
                                            CONTRACT_MECHANICAL_DEDUCTION_TERRITORY
                                        )}
                                    </Modal>
                                    <ContractMechanicalDeductionSidecar
                                        mechanicalDeduction={
                                            contractMechanicalDeduction
                                        }
                                        isSidecarOpen={isSidecarOpen}
                                        setIsSidecarOpen={setIsSidecarOpen}
                                    />
                                </Col>
                            </RestrictedByAbacusProfileWrapper>
                        </Row>
                    </Container>
                </Card.Title>
                <Card.Text className="ContractMechanicalDeductions-mechanicalDeductionCard-cardTextBody">
                    <span
                        className="ContractMechanicalDeductions-mechanicalDeductionCard-mechanicalTypesText"
                        data-testid="mechanicalTypeText"
                    >
                        {generateConcatenatedMechanicalTypesDisplayText(
                            contractMechanicalDeduction.mechanicalType
                        )}
                    </span>
                </Card.Text>
                <Card.Subtitle
                    data-testid="mechanicalDeductionPaidBy"
                    className="mb-2 text-muted ContractMechanicalDeductions-mechanicalDeductionCard-paidByText"
                >
                    Paid by{' '}
                    {contractMechanicalDeduction.adminType.toLowerCase()}
                    {contractMechanicalDeduction.adminFee !== null &&
                        ` · ${contractMechanicalDeduction.adminFee}% admin fee`}
                </Card.Subtitle>
            </Card.Body>
        </Card>
    );
};
