import { CSSProperties, FC, useRef } from "react";
import style from "./scheduleView.module.css";
import { useClipboardStore } from "@store/Clipboard.Store";
import { useAlert } from "@core/Store/Alert.Store";
import Avatar from "@components/Avatar/Avatar";

/**
 * Given a background color and two foreground color options, returns the
 * foreground color with the best contrast ratio to the background color.
 */
export const testContrast = (
    bg: CSSProperties["color"],
    fg1: CSSProperties["color"],
    fg2: CSSProperties["color"],
    skewReturnLighter: number = 0
): CSSProperties["color"] => {
    const bgLuminance = clamp(getLuminance(bg) - skewReturnLighter, 0, 1);
    const fg1Luminance = getLuminance(fg1);
    const fg2Luminance = getLuminance(fg2);

    const fg1Contrast = getContrast(bgLuminance, fg1Luminance);
    const fg2Contrast = getContrast(bgLuminance, fg2Luminance);

    return fg1Contrast > fg2Contrast ? fg1 : fg2;
};

/**
 * Returns the contrast ratio between two luminances
 */
export const getContrast = (bgLuminance: number, fgLuminance: number): number => {
    return Math.abs(bgLuminance - fgLuminance);
};

/**
 * Returns the luminance value of a CSS color
 */
export const getLuminance = (color: CSSProperties["color"]): number => {
    const rgb = cssColorToRGB(color);
    const r = rgb[0] / 255;
    const g = rgb[1] / 255;
    const b = rgb[2] / 255;

    const luminance = Math.sqrt(0.299 * r ** 2 + 0.587 * g ** 2 + 0.114 * b ** 2);
    return luminance;
};

/**
 * Converts a CSS color string to RGB values
 */
export const cssColorToRGB = (color: CSSProperties["color"]): number[] => {
    const isBrowser = typeof window !== "undefined";

    if (!color || !isBrowser) return [0, 0, 0];

    const canvas = document.createElement("canvas");
    canvas.width = 1;
    canvas.height = 1;

    const ctx = canvas.getContext("2d");
    if (!ctx) throw new Error("Could not get canvas context");

    ctx.fillStyle = color;
    ctx.fillRect(0, 0, 1, 1);

    const data = ctx.getImageData(0, 0, 1, 1).data;

    return [data[0], data[1], data[2]];
};

// https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/RGBToHSL.md
export const RGBToHSL = ([r, g, b]: number[]) => {
    r /= 255;
    g /= 255;
    b /= 255;
    const l = Math.max(r, g, b);
    const s = l - Math.min(r, g, b);
    const h = s ? (l === r ? (g - b) / s : l === g ? 2 + (b - r) / s : 4 + (r - g) / s) : 0;
    return [
        60 * h < 0 ? 60 * h + 360 : 60 * h,
        100 * (s ? (l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s))) : 0),
        (100 * (2 * l - s)) / 2,
    ];
};

export const SUBDIVISIONS_PER_HOUR = 12;

export interface DaySchedule<CustomCalendarEvent extends CalendarEvent = CalendarEvent> {
    name: string;
    events: CustomCalendarEvent[];
}

export interface CalendarEvent {
    startTime: number;
    endTime: number;
    title: string;
    description?: string;
    color?: CSSProperties["backgroundColor"];
}

// Rows/cols indexed starting from 1 to match CSS
export interface PositionedEvent<CustomCalendarEvent extends CalendarEvent> {
    event: CustomCalendarEvent;
    col: number;
    endCol: number;
    // Row numbers are relative to the first row of the event group
    row: number;
    endRow: number;
}

export interface PositionedEventGroup<CustomCalendarEvent extends CalendarEvent> {
    totalCols: number;
    groupStartRow: number;
    groupEndRow: number;
    positionedEvents: PositionedEvent<CustomCalendarEvent>[];
}

export type ScheduleThemeOverride = DeepPartial<ScheduleTheme>;

export type DeepPartial<T> = {
    [P in keyof T]?: DeepPartial<T[P]>;
};

export interface ScheduleTheme<CustomCalendarEvent extends CalendarEvent = CalendarEvent> {
    style?: ScheduleThemeStyle;
    hourHeight: CSSProperties["height"];
    minorGridlinesPerHour: number;
    timeRangeFormatter: (startTime: number, endTime: number) => string;
    timeFormatter: (time: number) => string;
    defaultTileColor:
        | CSSProperties["backgroundColor"]
        | ((event: CustomCalendarEvent) => CSSProperties["backgroundColor"]);
    customTileComponent?: FC<{ event: CustomCalendarEvent }>;
    themeTileContent?: FC<{ event: CustomCalendarEvent }>;
}

export interface ScheduleThemeStyle<CustomCalendarEvent extends CalendarEvent = CalendarEvent> {
    root?: CSSProperties;
    dayLabels?: CSSProperties;
    timeScaleLabels?: CSSProperties;
    eventTiles?:
        | CSSProperties
        | ((
              event: CustomCalendarEvent,
              theme: ScheduleTheme<CustomCalendarEvent>
          ) => CSSProperties);
    majorGridlinesBorder?: CSSProperties["borderStyle"];
    minorGridlinesBorder?: CSSProperties["borderStyle"];
    verticalGridlinesBorder?: CSSProperties["borderStyle"];
}

export const clamp = (value: number, min: number, max: number) =>
    Math.min(Math.max(value, min), max);

export const numToHHMM = (num: number) => {
    let hours = Math.floor(num) % 12;
    if (hours === 0) {
        hours = 12;
    }

    const minutes = Math.round((num % 1) * 60);

    return `${hours}:${minutes < 10 ? "0" : ""}${minutes} ${num >= 12 && num < 24 ? "PM" : "AM"}`;
};

export const numToHH = (num: number) => {
    let hours = Math.floor(num) % 12;
    if (hours === 0) {
        hours = 12;
    }

    return `${hours} ${num >= 12 && num < 24 ? "PM" : "AM"}`;
};

export const timeFormatter = (startTime: number) => `${numToHHMM(startTime)}`;

export const timeRangeFormatter = (startTime: number, endTime: number) =>
    `${numToHHMM(startTime)} - ${numToHHMM(endTime)}`;

export const googleColors = {
    greyGridline: "#a6a7ac",
    greyTimeLabel: "#94979b",
    greyDayLabel: "#666a6d",
    blue: "#5186EC",
    red: "#C3281C",
    yellow: "#EEC04B",
    purple: "#8332A4",
    green: "#397D49",
    indigo: "#4153AF",
    pink: "#C63461",
    lavender: "#AF9FD7",
    orange: "#E35C33",
    brown: "#74574A",
};

const calculateTextColor = (event: CalendarEvent, theme: ScheduleTheme): CSSProperties["color"] => {
    const defaultColor =
        typeof theme.defaultTileColor === "function"
            ? theme.defaultTileColor(event)
            : theme.defaultTileColor;

    return testContrast(event.color ?? defaultColor, "white", "black", 0.3);
};

const calculateBackgroundOpacity = (event: TXCalendarEvent): CSSProperties["opacity"] => {
    return event.appointmentId ? 1 : 0.7;
};

export interface TXCalendarEvent extends CalendarEvent {
    appointmentId?: string;
    clientId?: string;
    turnoId?: string;
    employeeId?: string;
    serviceId?: string;
    avatar?: string;
    repeatId?: string;
    payment?: boolean;
}

const TurnosXpressTitle = (props: { event: TXCalendarEvent }) => {
    let imageAvatar = "";
    
    const alert = useAlert();
    const setCopiedAppointment = useClipboardStore(state => state.setCopiedAppointment);
    
    const pressTimeout = useRef<NodeJS.Timeout | null>(null);
    const isLongPress = useRef(false);

    if (props.event.avatar) {
        imageAvatar = props.event.avatar;
    }
    
    const handleStart = (e: React.TouchEvent | React.MouseEvent) => {
        isLongPress.current = false;
        const target = e.currentTarget;
        
        target.parentElement?.classList.add(style.eventRowViewAnimated);
        
        pressTimeout.current = setTimeout(() => {
            isLongPress.current = true;
            target.parentElement?.classList.remove(style.eventRowViewAnimated);
            
            if (props.event.appointmentId) {
                setCopiedAppointment(props.event);
                alert.showSuccess("ID del turno copiado exitosamente.");
            }
        }, 500);
    };

    const handleCancel = (e: React.TouchEvent | React.MouseEvent) => {
        if (pressTimeout.current) {
            clearTimeout(pressTimeout.current);
            pressTimeout.current = null;
        }
        e.currentTarget.parentElement?.classList.remove(style.eventRowViewAnimated);
    };

    const handleClick = (e: React.MouseEvent) => {
        if (isLongPress.current) {
            e.stopPropagation();
            e.preventDefault();
        }
    };

    return (
        <div
            style={{ width: '100%', height: '100%' }}
            onTouchStart={handleStart}
            onTouchEnd={handleCancel}
            onTouchCancel={handleCancel}
            onTouchMove={handleCancel}
            onMouseDown={handleStart}
            onMouseUp={handleCancel}
            onMouseLeave={handleCancel}
            onClickCapture={handleClick}
        >
            <div className={style.turnosXpressTitleContent}>
                <Avatar
                    src={imageAvatar}
                    alt={props.event.title}
                    size="super-small"
                    border="none"
                    style={{ minWidth: "32px" }}
                />
                <h1>{props.event.title}</h1>
            </div>
            <div className={style.turnosXpressTimeContent}>
                {timeRangeFormatter(props.event.startTime, props.event.endTime)}
                {props.event.payment && (
                    <span style={{ marginLeft: "5px", marginTop: "5px" }}>💰</span>
                )}
            </div>
        </div>
    );
};

export const scViewTurnosExpress = (fractionTime: number = 60): ScheduleTheme<TXCalendarEvent> => {
    const rowHeight = (100 * 60) / fractionTime;

    return {
        style: {
            root: {
                fontFamily: "Kanit, Roboto, Helvetica, Arial, sans-serif",
            },
            dayLabels: {
                color: googleColors.greyDayLabel,
                textTransform: "uppercase",
            },
            timeScaleLabels: {
                color: googleColors.greyTimeLabel,
                fontSize: "0.7rem",
            },
            majorGridlinesBorder: `1px solid #dad8d8`,
            minorGridlinesBorder: `1px dotted ${googleColors.greyGridline}`,
            verticalGridlinesBorder: `1x solid ${googleColors.greyGridline}`,
            eventTiles: (event, theme) => ({
                color: calculateTextColor(event, theme),
                opacity: calculateBackgroundOpacity(event),
            }),
        },
        hourHeight: `${rowHeight}px`,
        minorGridlinesPerHour: 4,
        timeRangeFormatter: timeRangeFormatter,
        defaultTileColor: "var(--wine-darkest)",
        timeFormatter: numToHH,
        //customTileComponent: TurnosXpressTitle,
        themeTileContent: TurnosXpressTitle,
    };
};
