<?php

namespace KaizenCoders\MagicLink\Admin\Controllers;

use KaizenCoders\MagicLink\Admin\DB\MagicLinks;

class DashboardController {

	/** @var MagicLinks */
	private $db;

	public function __construct() {
		$this->db = new MagicLinks();
	}

	/**
	 * Return all data needed by the dashboard template.
	 *
	 * @param int  $days   Time-window for the trend chart (7 or 30).
	 * @param bool $is_pro Whether the current site has an active PRO licence.
	 */
	public function get_data( $days = 7, $is_pro = false ) {
		$tier      = $is_pro ? 'pro' : 'free';
		$cache_key = "kc_ml_dashboard_{$days}_{$tier}";
		$cached    = get_transient( $cache_key );

		if ( false !== $cached ) {
			return $cached;
		}

		$total    = $this->db->get_total_count();
		$used     = $this->db->get_used_count();
		$active   = $this->db->get_active_count();
		$unique   = $this->db->get_unique_users_count();
		$use_rate = $total > 0 ? round( ( $used / $total ) * 100 ) : 0;

		// Free users see 3 recent links; PRO users see 10.
		$recent_limit = $is_pro ? 10 : 3;

		$data = [
			'kpis'         => [
				[
					'title' => __( 'Links Generated', 'magic-link' ),
					'count' => $total,
					'sub'   => sprintf( __( 'Last %d days: %d', 'magic-link' ), $days, $this->db->get_recent_count( $days ) ),
					'color' => 'indigo',
					'icon'  => 'link',
				],
				[
					'title' => __( 'Links Used', 'magic-link' ),
					'count' => $used,
					'sub'   => $use_rate . '% ' . __( 'use rate', 'magic-link' ),
					'color' => 'green',
					'icon'  => 'check',
				],
				[
					'title' => __( 'Active Links', 'magic-link' ),
					'count' => $active,
					'sub'   => __( 'Not expired & unused', 'magic-link' ),
					'color' => 'blue',
					'icon'  => 'clock',
				],
				[
					'title' => __( 'Unique Users', 'magic-link' ),
					'count' => $unique,
					'sub'   => __( 'Users with a link', 'magic-link' ),
					'color' => 'purple',
					'icon'  => 'users',
				],
			],
			'chart_data'   => $this->prepare_chart_data( $days ),
			// Heatmap and top-users are PRO-only — skip the queries for free users.
			'heatmap_data' => $is_pro ? $this->prepare_heatmap_data() : null,
			'top_users'    => $is_pro ? $this->db->get_top_users( 5 ) : null,
			'recent_links' => $this->db->get_recent_links( $recent_limit ),
			'days'         => $days,
			'is_pro'       => $is_pro,
			'last_updated' => current_time( 'timestamp' ),
		];

		set_transient( $cache_key, $data, 30 * MINUTE_IN_SECONDS );

		return $data;
	}

	public function bust_cache( $is_pro = false ) {
		$tier = $is_pro ? 'pro' : 'free';
		foreach ( [ 7, 30 ] as $d ) {
			delete_transient( "kc_ml_dashboard_{$d}_{$tier}" );
		}
	}

	// -------------------------------------------------------------------------
	// Private helpers
	// -------------------------------------------------------------------------

	private function prepare_chart_data( $days ) {
		$rows    = $this->db->get_daily_trend( $days );
		$indexed = [];
		foreach ( $rows as $row ) {
			$indexed[ $row->date ] = $row;
		}

		$dates     = [];
		$generated = [];
		$used      = [];

		for ( $i = $days - 1; $i >= 0; $i-- ) {
			$date        = gmdate( 'Y-m-d', strtotime( "-{$i} days" ) );
			$dates[]     = $date;
			$generated[] = isset( $indexed[ $date ] ) ? (int) $indexed[ $date ]->generated : 0;
			$used[]      = isset( $indexed[ $date ] ) ? (int) $indexed[ $date ]->used : 0;
		}

		return compact( 'dates', 'generated', 'used' );
	}

	private function prepare_heatmap_data() {
		$rows    = $this->db->get_heatmap_data();
		$by_date = [];
		foreach ( $rows as $row ) {
			$by_date[ $row['date'] ] = (int) $row['count'];
		}

		$timezone = wp_timezone();
		$today    = new \DateTimeImmutable( 'today', $timezone );
		$start    = $today->modify( '-364 days' );

		// Rewind to Monday of that week.
		$dow   = (int) $start->format( 'N' ); // 1 = Mon … 7 = Sun
		if ( $dow > 1 ) {
			$start = $start->modify( '-' . ( $dow - 1 ) . ' days' );
		}

		$weeks   = [];
		$current = $start;

		while ( $current <= $today ) {
			$week_data = [];
			for ( $d = 0; $d < 7; $d++ ) {
				$date        = $current->format( 'Y-m-d' );
				$future      = $current > $today;
				$week_data[] = [
					'x'      => $date,
					'y'      => $future ? - 1 : ( isset( $by_date[ $date ] ) ? $by_date[ $date ] : 0 ),
					'future' => $future,
				];
				$current = $current->modify( '+1 day' );
			}
			$weeks[] = $week_data;
		}

		// Transpose to day-of-week rows × week columns (ApexCharts heatmap format).
		$day_names = [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ];
		$series    = [];
		for ( $d = 0; $d < 7; $d++ ) {
			$day_data = [];
			foreach ( $weeks as $week ) {
				if ( isset( $week[ $d ] ) ) {
					$day_data[] = $week[ $d ];
				}
			}
			$series[] = [ 'name' => $day_names[ $d ], 'data' => $day_data ];
		}

		// Dynamic color ranges based on data distribution.
		$all_counts = [];
		foreach ( $weeks as $week ) {
			foreach ( $week as $cell ) {
				if ( $cell['y'] > 0 ) {
					$all_counts[] = $cell['y'];
				}
			}
		}
		$max = ! empty( $all_counts ) ? max( $all_counts ) : 0;

		return [
			'series'       => $series,
			'color_ranges' => $this->heatmap_color_ranges( $max ),
		];
	}

	private function heatmap_color_ranges( $max ) {
		$ranges = [
			[ 'from' => - 1, 'to' => - 1, 'color' => '#f4f7fb', 'name' => '' ],
			[ 'from' => 0,   'to' => 0,   'color' => '#eef2ff', 'name' => '0' ],
		];

		if ( $max <= 0 ) {
			return $ranges;
		}

		$levels  = [ 0.16, 0.32, 0.48, 0.64, 0.80, 1.0 ];
		$colors  = [ '#c7d2fe', '#a5b4fc', '#818cf8', '#6366f1', '#4f46e5', '#3730a3' ];
		$prev    = 1;

		foreach ( $levels as $i => $pct ) {
			$to = max( $prev, (int) round( $max * $pct ) );

			$ranges[] = [
				'from'  => $prev,
				'to'    => $to,
				'color' => $colors[ $i ],
				'name'  => $prev === $to ? (string) $prev : "{$prev}–{$to}",
			];

			$prev = $to + 1;
		}

		return $ranges;
	}
}
