import type React from 'react';
import { useSelector } from 'react-redux';
import {
	LineChart,
	Line,
	XAxis,
	YAxis,
	CartesianGrid,
	Tooltip,
	ReferenceDot,
	ReferenceLine,
	ResponsiveContainer,
	Label,
	Customized
} from 'recharts';
import type { RootState } from '../../../../ReduxState/store';
import type { CompanyDbModel } from '../../../Companies/Components/CompaniesComponents.helper';
import type { FinancialsModel } from '../../../Financials/Components/FinancialsForm/FinancialsForm.helper';
import { moneyForGrowthCalculations } from '../../../../utils/moneyForGrowthCalculations';
import styles from '../../../MoneyForCeos/Components/MoneyForCeosChart.module.scss';
import globalStyle from '../../../../Components/GlobalStyles/globals.module.scss';

interface DataPoint {
	workingCapital: number;
	linearGrowth: number;
}

const GrowthStrategyChart: React.FC = () => {
	// hardcoded at client request
	const cashFlowOnGrowthLabel = 'linear growth';
	const borrowMoneyLabel = 'zig-zag growth';
	const selectedCompany = useSelector(
		(state: RootState): CompanyDbModel | null => state.companies.selectedCompany
	);
	const currencyLabel = `${
		typeof selectedCompany?.currency_symbol === 'string'
			? 'GBP'
			: selectedCompany?.currency_symbol.value
	}`;

	const selectedFinancials = useSelector(
		(state: RootState): FinancialsModel[] | null => state.financials.selectedFinancials
	);

	if (!selectedFinancials || selectedFinancials.length < 2) return <></>;
	const { input } = selectedFinancials[selectedFinancials.length - 1];
	const calculated = moneyForGrowthCalculations(input, 100);
	const {
		borrowMoney: calculatedBorrowMoney,
		requiredWorkingCapital,
		cashFlowOnGrowth,
		preTaxProfit
	} = calculated;

	const xVal = requiredWorkingCapital;
	// const xVal = 2500.25;
	const xValFormatted = xVal.toLocaleString('en-GB', {
		style: 'currency',
		currency: currencyLabel,
		minimumFractionDigits: 2,
		maximumFractionDigits: 2
	});
	const yVal = preTaxProfit;
	// const yVal = 150000.19;
	const yValFormatted = yVal.toLocaleString('en-GB', {
		style: 'currency',
		currency: currencyLabel,
		minimumFractionDigits: 2,
		maximumFractionDigits: 2
	});

	const dataPoint = { workingCapital: xVal, profit: yVal };

	// 1. Calculate symmetric domain range
	const maxRange = Math.max(dataPoint.workingCapital, dataPoint.profit);
	let roundTo = 3;

	if (maxRange > 10000) {
		roundTo = 10000;
	} else if (maxRange > 1000) {
		roundTo = 1000;
	} else if (maxRange > 100) {
		roundTo = 100;
	} else if (maxRange > 50) {
		roundTo = 100;
	} else if (maxRange > 5) {
		roundTo = 5;
	}

	const maxValue =
		maxRange > 5
			? Math.ceil(Math.ceil(maxRange * 1.1) / roundTo) * roundTo
			: Math.ceil(maxRange * 1.1);
	const axisDomain: [number, number] = [-maxValue, maxValue];

	// Step 3: Build the data from -max to +max (inclusive), step = 1
	const data: DataPoint[] = [];
	for (let x = axisDomain[0]; x <= axisDomain[1]; x++) {
		data.push({
			workingCapital: x,
			linearGrowth: x // y = x for a centered diagonal
		});
	}

	const generateTicks_deprecated = (domain: [number, number]): number[] => {
		const [min, max] = domain;

		// Determine an appropriate step size based on maxValue
		const maxAbs = Math.max(Math.abs(min), Math.abs(max));

		// Choose step size based on maxAbs
		let step = 1;

		if (maxAbs > 1000) {
			step = 500;
			// } else if (maxAbs > 500) {
			// 	step = 250;
		} else if (maxAbs > 100) {
			step = 50;
		} else if (maxAbs > 50) {
			step = 10;
		} else if (maxAbs > 10) {
			step = 5;
		} else if (maxAbs > 5) {
			step = 1;
		} else if (maxAbs > 1) {
			step = 0.2; // For small values, use fractional steps
		}

		// Generate ticks from -maxAbs to maxAbs, inclusive, with the calculated step
		const ticks = [];
		for (let i = Math.ceil(min / step) * step; i <= Math.floor(max / step) * step; i += step) {
			// Ensure zero is always included
			if (i >= min && i <= max) {
				ticks.push(i);
			}
		}

		// Always include zero explicitly if not already present
		if (!ticks.includes(0)) {
			ticks.push(0);
			ticks.sort((a, b) => a - b);
		}

		// Limit ticks for large max values
		if (maxAbs >= 1000 || ticks.length > 8) {
			// Include every other tick
			let ret = ticks.filter((_, index) => index % 2 === 0);
			console.log('reduced ticks', ret);

			if (ret.length > 8) {
				// Include every other tick
				ret = ret.filter((_, index) => index % 2 === 0);
				console.log('second reduction', ret);
			}
			return ret;
		}

		console.log('ticks', ticks);

		return ticks;
	};

	function getEqualDistancePoints(maxValue: number): number[] {
		// Find the smallest number >= maxValue that is divisible by 4
		const nextMultipleOfFour = Math.ceil(maxValue / 4) * 4;

		// Generate positive points (including zero)
		const positivePoints = [];
		for (let i = 0; i <= 4; i++) {
			positivePoints.push(i * (nextMultipleOfFour / 4));
		}

		// Generate negative points (excluding zero)
		const negativePoints = positivePoints.slice(1).map((point) => -point);

		// Combine negative points, zero, and positive points
		const allPoints = [...negativePoints, ...positivePoints];

		// Sort the combined array
		allPoints.sort((a, b) => a - b);

		return allPoints;
	}

	const generateTicks = (maxAbs: number): number[] => {
		const ticks = getEqualDistancePoints(maxAbs);
		return ticks;
	};

	const formatAsCurrency = (value: number): string => {
		const rounded =
			Math.abs(value) < 1
				? `${value.toLocaleString('en-GB', {
						style: 'currency',
						currency: currencyLabel,
						minimumFractionDigits: 1,
						maximumFractionDigits: 1
				  })}`
				: `${value.toLocaleString('en-GB', {
						style: 'currency',
						currency: currencyLabel,
						minimumFractionDigits: 0,
						maximumFractionDigits: 0
				  })}`;
		return `${rounded}`;
	};

	// Text annotations positioned in data coordinates
	const annotations = [
		{ x: -maxValue / 2.2, y: maxValue / 1.7, text: cashFlowOnGrowthLabel },
		{ x: maxValue / 1.5, y: -maxValue / 2.3, text: borrowMoneyLabel }
	];

	return (
		<div style={{ paddingTop: '20px' }}>
			<h3 className={globalStyle.title}>Growth Strategy</h3>

			<ResponsiveContainer width={430} height={430} aspect={1}>
				<LineChart data={data} margin={{ top: 20, right: 30, left: 30, bottom: 40 }}>
					<CartesianGrid strokeDasharray="3 3" />

					{/* Fake crossed axes */}
					<ReferenceLine x={0} stroke="black" strokeWidth={2} />
					<ReferenceLine y={0} stroke="black" strokeWidth={2} />

					<XAxis
						type="number"
						dataKey="workingCapital"
						domain={axisDomain}
						tickCount={axisDomain[1] * 2 + 1}
						axisLine={false}
						tickLine
						allowDecimals={false}
						tick={{ fontSize: 11 }}
						ticks={generateTicks(axisDomain[1])}
						interval={0}
						tickFormatter={(value) => formatAsCurrency(value)}
					>
						<Label
							value={`Working capital per 100 ${currencyLabel} sale`}
							position="insideBottom"
							offset={-15}
							style={{ fontSize: 12, fill: '#000' }}
						/>
					</XAxis>

					<YAxis
						type="number"
						domain={axisDomain}
						tickCount={axisDomain[1] * 2 + 1}
						axisLine={false}
						tickLine
						allowDecimals={false}
						tick={{ fontSize: 11 }}
						ticks={generateTicks(axisDomain[1])}
						interval={0}
						tickFormatter={(value) => formatAsCurrency(value)}
					>
						<Label
							value={`Net Profit (pre-tax) per 100 ${currencyLabel} sale`}
							angle={-90}
							position="insideLeft"
							offset={0}
							style={{ fontSize: 12, fill: '#000' }}
							dy={90}
						/>
					</YAxis>

					<Tooltip />
					<Line
						type="monotone"
						dataKey="linearGrowth"
						stroke="#8884d8"
						strokeWidth={2}
						dot={false}
						name="Linear Growth"
					/>
					<ReferenceDot
						x={dataPoint.workingCapital}
						y={dataPoint.profit}
						r={6}
						fill="red"
						stroke="none"
						// label={{
						// 	value: 'Zip-Tap Growth',
						// 	position: 'top',
						// 	fill: 'red'
						// }}
					/>

					<Customized
						// @ts-ignore
						component={({ xAxisMap, yAxisMap }) =>
							annotations.map((ann, i) => {
								const xScale = xAxisMap['0'].scale;
								const yScale = yAxisMap['0'].scale;

								return (
									<text
										key={i}
										x={xScale(ann.x)}
										y={yScale(ann.y)}
										fill="#444"
										fontSize={12}
										textAnchor="middle"
									>
										{ann.text}
									</text>
								);
							})
						}
					/>
				</LineChart>
			</ResponsiveContainer>
		</div>
	);
};

export default GrowthStrategyChart;
