<?php

namespace _121Digital\Connect\Network\Services;

use _121Digital\Connect\Network\Models\NewSiteDTO;
use _121Digital\Connect\Network\Models\SiteDTO;

class NodeSiteService
{
    /**
     * Retrieves all sites in the multisite network.
     *
     * @param bool $detailed Whether to load detailed information (includes site options). Default false for performance.
     * @return SiteDTO[] Array of SiteDTO objects representing the sites.
     */
    public static function getAllSites(bool $detailed = false): array
    {
        $sites = [];
        $wpSites = get_sites();

        foreach ($wpSites as $wpSite) {
            $siteDetails = get_site($wpSite->blog_id);

            if ($detailed) {
                // Load detailed information including site options
                switch_to_blog($wpSite->blog_id);

                $siteName = get_option('blogname');
                $siteDescription = get_option('blogdescription');
                $siteLanguage = get_option('WPLANG');
                $adminEmail = get_option('admin_email');
                $visibility = get_option('blog_public');

                restore_current_blog();

                $sites[] = new SiteDTO(
                    siteId: $siteDetails->blog_id,
                    siteName: $siteName,
                    domain: $siteDetails->domain,
                    path: $siteDetails->path,
                    adminEmail: $adminEmail,
                    siteDescription: $siteDescription,
                    language: $siteLanguage,
                    visibility: $visibility,
                    archived: $siteDetails->archived == '1',
                    spam: $siteDetails->spam == '1',
                    deleted: $siteDetails->deleted == '1',
                    mature: $siteDetails->mature == '1',
                    registered: $siteDetails->registered,
                    lastUpdated: $siteDetails->last_updated
                );
            } else {
                // Load basic information (faster for list views)
                $sites[] = new SiteDTO(
                    siteId: $siteDetails->blog_id,
                    siteName: $siteDetails->blogname,
                    domain: $siteDetails->domain,
                    path: $siteDetails->path,
                    adminEmail: $siteDetails->admin_email,
                    siteDescription: null,
                    language: null,
                    visibility: null,
                    archived: $siteDetails->archived == '1',
                    spam: $siteDetails->spam == '1',
                    deleted: $siteDetails->deleted == '1',
                    mature: $siteDetails->mature == '1',
                    registered: $siteDetails->registered,
                    lastUpdated: $siteDetails->last_updated
                );
            }
        }

        return $sites;
    }

    /**
     * Creates a new site in the multisite network based on the provided SiteDTO.
     *
     * @param SiteDTO $siteDTO The data transfer object containing site details.
     * @return int The ID of the newly created site.
     * @throws \Exception If site creation fails.
     */
    public function createSite(NewSiteDTO $siteDTO): int
    {
        $siteData = [
          'domain' => $siteDTO->getDomain(),
          'path' => $siteDTO->getPath(),
          'title' => $siteDTO->getSiteName(),
          'admin_email' => $siteDTO->getAdminEmail(),
        ];

        $siteId = wp_insert_site($siteData);

        if (is_wp_error($siteId)) {
            throw new \Exception(__('Failed to create site: ', '121-connect') . $siteId->get_error_message());
        }

        return $siteId;
    }

    /**
     * Updates site details for an existing site.
     *
     * @param SiteDTO $siteDTO The data transfer object containing site details to update.
     * @return bool True on success, false on failure.
     * @throws \Exception If site update fails.
     */
    public static function updateSite(SiteDTO $siteDTO): bool
    {
        $siteId = $siteDTO->getSiteId();

        if (!$siteId) {
            throw new \Exception(__('Site ID is required for update.', '121-connect'));
        }

        if (!get_site($siteId)) {
            throw new \Exception(__('Site not found.', '121-connect'));
        }

        // Switch to the site to update its options
        switch_to_blog($siteId);

        try {
            // Update site options (only if set in DTO)
            if ($siteDTO->getSiteName() !== null) {
                update_option('blogname', sanitize_text_field($siteDTO->getSiteName()));
            }

            if ($siteDTO->getSiteDescription() !== null) {
                update_option('blogdescription', sanitize_text_field($siteDTO->getSiteDescription()));
            }

            if ($siteDTO->getAdminEmail() !== null) {
                update_option('admin_email', sanitize_email($siteDTO->getAdminEmail()));
            }

            if ($siteDTO->getLanguage() !== null) {
                update_option('WPLANG', sanitize_text_field($siteDTO->getLanguage()));
            }

            if ($siteDTO->getVisibility() !== null) {
                update_option('blog_public', sanitize_text_field($siteDTO->getVisibility()));
            }

            restore_current_blog();

            // Update site attributes in the sites table
            $updateData = [];

            if ($siteDTO->isArchived() !== null) {
                $updateData['archived'] = $siteDTO->isArchived() ? '1' : '0';
            }

            if ($siteDTO->isSpam() !== null) {
                $updateData['spam'] = $siteDTO->isSpam() ? '1' : '0';
            }

            if ($siteDTO->isDeleted() !== null) {
                $updateData['deleted'] = $siteDTO->isDeleted() ? '1' : '0';
            }

            if ($siteDTO->isMature() !== null) {
                $updateData['mature'] = $siteDTO->isMature() ? '1' : '0';
            }

            // Update the site in the database if we have attributes to update
            if (!empty($updateData)) {
                $result = wp_update_site($siteId, $updateData);

                if (is_wp_error($result)) {
                    throw new \Exception(__('Failed to update site attributes: ', '121-connect') . $result->get_error_message());
                }
            }

            return true;
        } catch (\Exception $e) {
            restore_current_blog();
            throw $e;
        }
    }

    /**
     * Retrieves detailed site information for a specific site.
     *
     * @param int $siteId The site ID.
     * @return SiteDTO Site information as a DTO.
     * @throws \Exception If site not found.
     */
    public static function getSiteDetails(int $siteId): SiteDTO
    {
        $siteDetails = get_site($siteId);

        if (!$siteDetails) {
            throw new \Exception(__('Site not found.', '121-connect'));
        }

        // Switch to the site to get its options
        switch_to_blog($siteId);

        $siteName = get_option('blogname');
        $siteDescription = get_option('blogdescription');
        $siteLanguage = get_option('WPLANG');
        $adminEmail = get_option('admin_email');
        $visibility = get_option('blog_public');

        restore_current_blog();

        return new SiteDTO(
            siteId: $siteDetails->blog_id,
            siteName: $siteName,
            domain: $siteDetails->domain,
            path: $siteDetails->path,
            adminEmail: $adminEmail,
            siteDescription: $siteDescription,
            language: $siteLanguage,
            visibility: $visibility,
            archived: $siteDetails->archived == '1',
            spam: $siteDetails->spam == '1',
            deleted: $siteDetails->deleted == '1',
            mature: $siteDetails->mature == '1',
            registered: $siteDetails->registered,
            lastUpdated: $siteDetails->last_updated
        );
    }
}
