<?php

namespace MeowCrew\CancellationOffers\Offer\Entity;

use MeowCrew\CancellationOffers\Offer\Entity\DiscountOffer\DiscountOffer;
use MeowCrew\CancellationOffers\Offer\Entity\MatchingRule\MatchingRule;
use MeowCrew\CancellationOffers\Offer\Entity\Statistics\Statistics;
use MeowCrew\CancellationOffers\Offer\CPT\CancellationOffersCPT;
use MeowCrew\CancellationOffers\Offer\Entity\Settings\Settings;
use MeowCrew\CancellationOffers\Offer\Entity\Survey\Survey;
use WC_Subscription;
use Exception;
use WP_User;
class Offer {
    protected $id;

    protected $matchingRule = null;

    protected $survey = null;

    protected $discountOffers = [];

    protected $offerSettings = null;

    protected $statistics = null;

    public function __construct(
        ?int $id,
        MatchingRule $matchingRule,
        Survey $survey,
        $discountOffers,
        Settings $offerSettings
    ) {
        $this->id = $id;
        $this->matchingRule = $matchingRule;
        $this->survey = $survey;
        if ( !is_array( $discountOffers ) ) {
            $discountOffers = ( $discountOffers ? [$discountOffers] : [] );
        }
        $this->discountOffers = $discountOffers;
        $this->offerSettings = $offerSettings;
    }

    public function setId( ?int $id ) {
        $this->id = $id;
    }

    public function getId() : int {
        return $this->id;
    }

    public function getMatchingRule() : ?MatchingRule {
        return $this->matchingRule;
    }

    public function getSurvey() : ?Survey {
        return $this->survey;
    }

    public function getDiscountOffer() : ?DiscountOffer {
        return $this->discountOffers[0] ?? null;
    }

    public function getDiscountOffers() : array {
        return $this->discountOffers;
    }

    public function getOfferByIdOrIndex( $idOrIndex ) : ?DiscountOffer {
        return $this->discountOffers[$idOrIndex] ?? null;
    }

    public function getSettings() : ?Settings {
        return $this->offerSettings;
    }

    public function getStatistics() : ?Statistics {
        if ( null === $this->statistics ) {
            $this->statistics = new Statistics($this);
        }
        return $this->statistics;
    }

    public static function build( int $offerId ) {
        if ( !get_post_status( $offerId ) || get_post_type( $offerId ) !== CancellationOffersCPT::SLUG ) {
            return false;
        }
        $matchingRule = MatchingRule::build( $offerId );
        // Load multiple offers
        $offersData = get_post_meta( $offerId, '_cancellation_offers_discount_offers_list', true );
        $discounts = [];
        $offerSettings = Settings::build( $offerId );
        $offerSurvey = Survey::build( $offerId );
        return new self(
            $offerId,
            $matchingRule,
            $offerSurvey,
            $discounts,
            $offerSettings
        );
    }

    public static function buildFromPOST( int $offerId, array $postedData ) : self {
        $matchingRule = MatchingRule::buildFromPOST( $postedData );
        $discounts = [];
        if ( isset( $postedData['discount_offers'] ) && is_array( $postedData['discount_offers'] ) ) {
            foreach ( $postedData['discount_offers'] as $offerData ) {
                $discounts[] = DiscountOffer::buildFromPOST( $offerData );
            }
        } else {
            // Check for legacy single structure
            // If discount_offer_title is present, it's legacy single
            if ( isset( $postedData['discount_offer_title'] ) || isset( $postedData['discount_offer_offer_type'] ) ) {
                $discounts[] = DiscountOffer::buildFromPOST( $postedData );
            }
        }
        // Handle "Add New" action trigger from frontend
        if ( !empty( $postedData['cancellation_offer_add_new_row'] ) ) {
            $discounts[] = DiscountOffer::buildDefault();
        }
        $offerSettings = Settings::buildFromPOST( $postedData );
        $offerSurvey = Survey::buildFromPOST( $postedData );
        return new self(
            $offerId,
            $matchingRule,
            $offerSurvey,
            $discounts,
            $offerSettings
        );
    }

    public function isApplicableForUser( ?WP_User $user, ?WC_Subscription $subscription ) : bool {
        if ( !$user || !$subscription ) {
            return false;
        }
        if ( $subscription->get_user_id() !== $user->ID ) {
            return false;
        }
        if ( !$this->isValid() ) {
            return false;
        }
        if ( !$this->getSettings()->matchRequirements( $user, $subscription ) ) {
            return false;
        }
        if ( !$this->getMatchingRule()->matchRequirements( $user, $subscription ) ) {
            return false;
        }
        // Check if ANY discount offer is applicable if survey disabled?
        $hasApplicableDiscount = false;
        foreach ( $this->discountOffers as $offer ) {
            if ( $offer->isApplicableForSubscription( $subscription ) ) {
                $hasApplicableDiscount = true;
                break;
            }
        }
        if ( !$this->getSurvey()->isEnabled() && !$hasApplicableDiscount ) {
            return false;
        }
        return true;
    }

    public function isValid() : bool {
        try {
            $this->validate();
        } catch ( Exception $e ) {
            return false;
        }
        return true;
    }

    /**
     * Validate offer
     *
     * @throws Exception
     */
    public function validate() : void {
        $hasEnabledDiscount = false;
        foreach ( $this->discountOffers as $offer ) {
            if ( $offer->isEnabled() ) {
                $hasEnabledDiscount = true;
                if ( !$offer->getCouponId() && $offer->getOfferType() === 'coupon' ) {
                    $message = sprintf( 
                        // translators: %s is the offer title.
                        esc_html__( 'Coupon code is required for enabled discount offer: %s', 'cancellation-surveys-offers-woocommerce-subscriptions' ),
                        $offer->getTitle()
                     );
                    throw new Exception($message);
                }
            }
        }
        if ( !$hasEnabledDiscount && !$this->getSurvey()->isEnabled() ) {
            throw new Exception(esc_html__( 'At least one of the offer types (discount or survey) must be enabled', 'cancellation-surveys-offers-woocommerce-subscriptions' ));
        }
        if ( $this->getSurvey()->isEnabled() && !$this->getSurvey()->getItems() ) {
            throw new Exception(esc_html__( 'Survey items are required for survey offer', 'cancellation-surveys-offers-woocommerce-subscriptions' ));
        }
    }

    public function save() {
        $this->matchingRule->save( $this->getId() );
        $offersData = [];
        update_post_meta( $this->getId(), '_cancellation_offers_discount_offers_list', $offersData );
        $this->offerSettings->save( $this->getId() );
        $this->survey->save( $this->getId() );
    }

}
