<?php
namespace BLR\Backline\Modules\Discography;

use BLR\Backline\Core\Access;
use BLR\Backline\Core\AdminMenu;
use BLR\Backline\Core\Sanitizer;

if (!defined('ABSPATH')) { exit; }

final class Module {
    private const RELEASE_TYPE_MIGRATION_BATCH_SIZE = 100;


    /**
     * Register CPTs/meta only. Front-end routes are hard-coded in the core Router.
     */
    public static function register_feature_only(): void {
        add_action('init', [self::class, 'register_cpts']);
        add_action('init', [self::class, 'register_meta'], 11);
    }


    public static function register_cpts(): void {
        $common = [
            'public'              => false,
            'publicly_queryable'  => false,
            'exclude_from_search' => true,
            'show_ui'             => false,
            'show_in_menu'        => false,
            'show_in_rest'        => false,
            'show_in_nav_menus'   => false,
            'has_archive'         => false,
            'rewrite'             => false,
            'query_var'           => false,
            'supports'            => ['title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'revisions', 'author'],
        ];

        register_post_type(
            'blr_release',
            array_replace_recursive(
                $common,
                Access::post_type_registration_args('blr_release'),
                [
                    'labels' => [
                        'name'          => __('Albums', 'blr-backline'),
                        'singular_name' => __('Album', 'blr-backline'),
                    ],
                    'menu_icon' => 'dashicons-album',
                ]
            )
        );

        register_taxonomy('blr_release_type', ['blr_release'], array_merge([
            'labels' => [
                'name' => __('Album Types', 'blr-backline'),
                'singular_name' => __('Album Type', 'blr-backline'),
            ],
            'public' => false,
            'show_ui' => false,
            'show_in_rest' => false,
            'show_admin_column' => true,
            'hierarchical' => false,
            'rewrite' => false,
        ], Access::taxonomy_registration_args('blr_release_type')));

        register_taxonomy('blr_release_status', ['blr_release', 'blr_track'], array_merge([
            'labels' => [
                'name' => __('Release Statuses', 'blr-backline'),
                'singular_name' => __('Release Status', 'blr-backline'),
            ],
            'public' => false,
            'show_ui' => false,
            'show_in_rest' => false,
            'show_admin_column' => true,
            'hierarchical' => false,
            'rewrite' => false,
        ], Access::taxonomy_registration_args('blr_release_status')));

        self::ensure_release_type_terms();
        self::ensure_release_status_terms();

        register_post_type('blr_track', array_merge($common, Access::post_type_registration_args('blr_track'), [
            'labels' => [
                'name' => __('Tracks', 'blr-backline'),
                'singular_name' => __('Track', 'blr-backline'),
            ],
            'menu_icon' => 'dashicons-format-audio',
        ]));
    }

    /** Seed common album-type terms once. */
    private static function ensure_release_type_terms(): void {
        if (!taxonomy_exists('blr_release_type')) {
            return;
        }

        $flag = (string) get_option('blr_ba_seeded_release_types', '');
        $need_seed = ($flag !== '1');

        $defaults = [
            'EP',
            'LP',
            'Album',
            'Compilation',
            'Live',
        ];

        if ($need_seed) {
            foreach ($defaults as $name) {
                $exists = term_exists($name, 'blr_release_type');
                if (!$exists) {
                    wp_insert_term($name, 'blr_release_type');
                }
            }
            update_option('blr_ba_seeded_release_types', '1', false);
        }

        self::remove_empty_single_type_term();
        self::migrate_release_type_meta_once();
    }

    private static function remove_empty_single_type_term(): void {
        $single = get_term_by('slug', 'single', 'blr_release_type');
        if (!$single || is_wp_error($single)) {
            $single = get_term_by('name', 'Single', 'blr_release_type');
        }

        if ($single && !is_wp_error($single) && (int) $single->count === 0) {
            wp_delete_term((int) $single->term_id, 'blr_release_type');
        }
    }

    private static function ensure_release_status_terms(): void {
        if (!taxonomy_exists('blr_release_status')) {
            return;
        }

        $flag = (string) get_option('blr_ba_seeded_release_statuses', '');
        if ($flag !== '1') {
            foreach (['Unreleased', 'Released'] as $name) {
                $exists = term_exists($name, 'blr_release_status');
                if (!$exists) {
                    wp_insert_term($name, 'blr_release_status');
                }
            }
            update_option('blr_ba_seeded_release_statuses', '1', false);
        }
    }

    private static function migrate_release_type_meta_once(): void {
        $done = (string) get_option('blr_ba_migrated_release_types', '');
        if ($done === '1') {
            return;
        }

        $page = max(1, (int) get_option('blr_ba_migrated_release_types_page', 1));

        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- One-time migration query for legacy release type meta.
        $q = new \WP_Query([
            'post_type' => 'blr_release',
            'post_status' => ['publish','draft','pending','private','trash'],
            'posts_per_page' => self::RELEASE_TYPE_MIGRATION_BATCH_SIZE,
            'fields' => 'ids',
            'no_found_rows' => true,
            'paged' => $page,
            'orderby' => 'ID',
            'order' => 'ASC',
            'meta_query' => [
                [
                    'key' => 'blr_release_type',
                    'value' => '',
                    'compare' => '!=',
                ]
            ],
        ]);

        if (!empty($q->posts)) {
            foreach ($q->posts as $pid) {
                $pid = (int) $pid;
                if (!$pid) {
                    continue;
                }

                $existing_terms = wp_get_object_terms($pid, 'blr_release_type', ['fields' => 'ids']);
                if (!is_wp_error($existing_terms) && !empty($existing_terms)) {
                    continue;
                }

                $legacy = trim((string) get_post_meta($pid, 'blr_release_type', true));
                if ($legacy === '' || strtolower($legacy) === 'single') {
                    continue;
                }

                $term = term_exists($legacy, 'blr_release_type');
                if (!$term) {
                    $ins = wp_insert_term($legacy, 'blr_release_type');
                    if (!is_wp_error($ins) && !empty($ins['term_id'])) {
                        $term = (int) $ins['term_id'];
                    }
                }

                $tid = 0;
                if (is_array($term) && !empty($term['term_id'])) {
                    $tid = (int) $term['term_id'];
                } elseif (is_int($term) && $term > 0) {
                    $tid = $term;
                }

                if ($tid) {
                    wp_set_object_terms($pid, [$tid], 'blr_release_type', false);
                }
            }
        }

        if (count($q->posts) >= self::RELEASE_TYPE_MIGRATION_BATCH_SIZE) {
            update_option('blr_ba_migrated_release_types_page', $page + 1, false);
            return;
        }

        update_option('blr_ba_migrated_release_types', '1', false);
    }

    public static function register_meta(): void {
        // Album meta (comprehensive starter set)
        self::reg_meta('blr_release', 'blr_release_date', 'string');
        self::reg_meta('blr_release', 'blr_release_type', 'string');
        self::reg_meta('blr_release', 'blr_artist', 'string');
        self::reg_meta('blr_release', 'blr_label', 'string');
        self::reg_meta('blr_release', 'blr_catalog_number', 'string');
        self::reg_meta('blr_release', 'blr_upc', 'string');
        self::reg_meta('blr_release', 'blr_genre', 'string');
        self::reg_meta('blr_release', 'blr_subgenre', 'string');
        self::reg_meta('blr_release', 'blr_mood', 'string');
        self::reg_meta('blr_release', 'blr_description_short', 'string');
        self::reg_meta('blr_release', 'blr_credits', 'string');
        self::reg_meta('blr_release', 'blr_presskit_url', 'string');
        self::reg_meta('blr_release', 'blr_spotify_url', 'string');
        self::reg_meta('blr_release', 'blr_apple_music_url', 'string');
        self::reg_meta('blr_release', 'blr_bandcamp_url', 'string');
        self::reg_meta('blr_release', 'blr_youtube_url', 'string');
        self::reg_meta('blr_release', 'blr_soundcloud_url', 'string');
        self::reg_meta('blr_release', 'blr_release_notes', 'string');

        // Relationship (track IDs)
        self::reg_meta_array_int('blr_release', 'blr_track_ids');

        // Track meta
        self::reg_meta('blr_track', 'blr_track_number', 'number');
        self::reg_meta('blr_track', 'blr_disc_number', 'number');
        self::reg_meta('blr_track', 'blr_duration', 'string');
        self::reg_meta('blr_track', 'blr_bpm', 'number');
        self::reg_meta('blr_track', 'blr_key', 'string');
        self::reg_meta('blr_track', 'blr_isrc', 'string');
        self::reg_meta('blr_track', 'blr_upc', 'string');
        self::reg_meta('blr_track', 'blr_explicit', 'string');
        self::reg_meta('blr_track', 'blr_instrumental', 'string');
        self::reg_meta('blr_track', 'blr_lyrics', 'string');
        self::reg_meta('blr_track', 'blr_credits', 'string');
        self::reg_meta('blr_track', 'blr_audio_url', 'string');
        self::reg_meta('blr_track', 'blr_audio_attachment_id', 'number');
        self::reg_meta('blr_track', 'blr_preview_start', 'number');
        self::reg_meta('blr_track', 'blr_notes', 'string');
        self::reg_meta('blr_track', 'blr_release_date', 'string');
        self::reg_meta('blr_track', 'blr_artist', 'string');
        self::reg_meta('blr_track', 'blr_spotify_url', 'string');
        self::reg_meta('blr_track', 'blr_apple_music_url', 'string');
        self::reg_meta('blr_track', 'blr_bandcamp_url', 'string');
        self::reg_meta('blr_track', 'blr_youtube_url', 'string');
        self::reg_meta('blr_track', 'blr_soundcloud_url', 'string');
        self::reg_meta('blr_track', 'blr_release_notes', 'string');
    }

    private static function reg_meta(string $post_type, string $key, string $type): void {
        register_post_meta($post_type, $key, [
            'type' => $type,
            'single' => true,
            'show_in_rest' => false,
            'sanitize_callback' => static function ($value) use ($key, $type) {
                return Sanitizer::meta_value($key, $value, $type);
            },
            'auth_callback' => Access::rest_meta_auth_callback($post_type),
        ]);
    }

    private static function reg_meta_array_int(string $post_type, string $key): void {
        register_post_meta($post_type, $key, [
            'single' => true,
            'type' => 'array',
            'default' => [],
            'show_in_rest' => [
                'schema' => [
                    'type' => 'array',
                    'items' => ['type' => 'integer'],
                ]
            ],
            'sanitize_callback' => [Sanitizer::class, 'id_array'],
            'auth_callback' => Access::rest_meta_auth_callback($post_type),
        ]);
    }
}