/*
  PHASE 1 — Create UserPackagePurchases (Manual=3) only.

  Scope: 17 users with verified manualy charge — both WalletHistory AND Transaction exist
         and WH.RefrenceId already points to the Tx.

  Hardcoded mapping (from UserWalletHistories.csv + Transactions.csv):

    UserId  WH    Tx
    ------  ----  ----
      75    102    23
      93    103    24
      96    104    25
      99    105    26
      47    106    28
      43    107    29
      45    108    30
      52    122    31
     116    138    42
     115    139    43
     119    140    44
     113    141    45
     103    142    46
     170    292   107
     171    293   108
     172    294   109
     175    295   110

  Does NOT:
    - change Users / Club / Cycle PurchaseMethod
    - create or modify Transactions or WalletHistory
    - re-charge wallet

  PackagePurchaseMethod on UPP: Manual = 3

  Defaults to ROLLBACK. Uncomment COMMIT after reviewing preview + counts.
*/

SET NOCOUNT ON;
SET XACT_ABORT ON;

BEGIN TRAN;

DECLARE @Now DATETIME2 = SYSUTCDATETIME();

DECLARE @BasePackageId BIGINT;
DECLARE @BasePackagePrice BIGINT;

SELECT TOP (1)
    @BasePackageId = Id,
    @BasePackagePrice = Price
FROM CMS.Packages
WHERE IsDeleted = 0 AND IsBasePackage = 1
ORDER BY Id;

IF @BasePackageId IS NULL
    THROW 50001, 'Base package not found.', 1;

------------------------------------------------------------
-- Expected mapping
------------------------------------------------------------
DECLARE @Phase1 TABLE (
    UserId BIGINT NOT NULL,
    WalletHistoryId BIGINT NOT NULL,
    TransactionId BIGINT NOT NULL,
    PRIMARY KEY (UserId)
);

INSERT INTO @Phase1 (UserId, WalletHistoryId, TransactionId) VALUES
(75,  102,  23),
(93,  103,  24),
(96,  104,  25),
(99,  105,  26),
(47,  106,  28),
(43,  107,  29),
(45,  108,  30),
(52,  122,  31),
(116, 138,  42),
(115, 139,  43),
(119, 140,  44),
(113, 141,  45),
(103, 142,  46),
(170, 292, 107),
(171, 293, 108),
(172, 294, 109),
(175, 295, 110);

DECLARE @Phase1Count INT = (SELECT COUNT(*) FROM @Phase1);
PRINT CONCAT('Phase1 expected rows: ', @Phase1Count);

------------------------------------------------------------
-- Validate live DB matches expected mapping
------------------------------------------------------------
SELECT
    p.UserId,
    u.Mobile,
    u.FirstName,
    u.LastName,
    p.WalletHistoryId AS ExpectedWhId,
    p.TransactionId AS ExpectedTxId,
    h.Id AS ActualWhId,
    h.RefrenceId AS ActualWhRefrenceId,
    h.ChangeValue AS WhChangeValue,
    t.Id AS ActualTxId,
    t.RefId AS TxRefId,
    t.Amount AS TxAmount,
    t.PaymentStatus,
    w.UserId AS WhWalletUserId,
    CASE
        WHEN u.Id IS NULL THEN N'USER_MISSING'
        WHEN h.Id IS NULL THEN N'WH_MISSING'
        WHEN t.Id IS NULL THEN N'TX_MISSING'
        WHEN h.RefrenceId <> p.TransactionId THEN N'WH_REF_MISMATCH'
        WHEN w.UserId <> p.UserId THEN N'WH_WALLET_USER_MISMATCH'
        WHEN t.RefId NOT LIKE N'manualy%' THEN N'TX_NOT_MANUALY'
        WHEN t.PaymentStatus <> 0 THEN N'TX_NOT_SUCCESS'
        ELSE N'OK'
    END AS ValidationStatus
FROM @Phase1 p
LEFT JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0
LEFT JOIN CMS.UserWalletHistories h ON h.Id = p.WalletHistoryId AND h.IsDeleted = 0
LEFT JOIN CMS.UserWallets w ON w.Id = h.WalletId AND w.IsDeleted = 0
LEFT JOIN CMS.Transactions t ON t.Id = p.TransactionId AND t.IsDeleted = 0
ORDER BY p.UserId;

DECLARE @BadValidation INT = (
    SELECT COUNT(*)
    FROM @Phase1 p
    LEFT JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0
    LEFT JOIN CMS.UserWalletHistories h ON h.Id = p.WalletHistoryId AND h.IsDeleted = 0
    LEFT JOIN CMS.UserWallets w ON w.Id = h.WalletId AND w.IsDeleted = 0
    LEFT JOIN CMS.Transactions t ON t.Id = p.TransactionId AND t.IsDeleted = 0
    WHERE u.Id IS NULL
       OR h.Id IS NULL
       OR t.Id IS NULL
       OR h.RefrenceId <> p.TransactionId
       OR w.UserId <> p.UserId
       OR t.RefId NOT LIKE N'manualy%'
       OR t.PaymentStatus <> 0
);

IF @BadValidation > 0
BEGIN
    DECLARE @BadMsg NVARCHAR(200);
    SET @BadMsg = CONCAT(
        N'Validation failed for ', @BadValidation,
        N' row(s). Fix before creating UPP.'
    );
    ROLLBACK;
    RAISERROR(@BadMsg, 16, 1);
    RETURN;
END

PRINT 'Validation OK for all 17 rows.';

------------------------------------------------------------
-- Preview: who already has UPP / UPP on this Tx
------------------------------------------------------------
SELECT
    p.UserId,
    u.Mobile,
    p.TransactionId,
    CASE WHEN upp_any.Id IS NOT NULL THEN N'YES' ELSE N'NO' END AS HasAnyUpp,
    upp_any.Id AS ExistingUppId,
    upp_any.PurchaseMethod AS ExistingUppMethod,
    upp_any.TransactionId AS ExistingUppTxId,
    CASE
        WHEN upp_tx.Id IS NOT NULL THEN N'SKIP_UPP_EXISTS_FOR_TX'
        WHEN upp_any.Id IS NOT NULL THEN N'SKIP_USER_HAS_OTHER_UPP'
        ELSE N'CREATE_UPP'
    END AS PlanAction
FROM @Phase1 p
INNER JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0
OUTER APPLY (
    SELECT TOP (1) upp.Id, upp.PurchaseMethod, upp.TransactionId
    FROM CMS.UserPackagePurchases upp
    WHERE upp.UserId = p.UserId AND upp.IsDeleted = 0
    ORDER BY upp.Id DESC
) upp_any
OUTER APPLY (
    SELECT TOP (1) upp.Id
    FROM CMS.UserPackagePurchases upp
    WHERE upp.UserId = p.UserId
      AND upp.IsDeleted = 0
      AND upp.TransactionId = p.TransactionId
    ORDER BY upp.Id DESC
) upp_tx
ORDER BY p.UserId;

------------------------------------------------------------
-- Build UPP insert plan
------------------------------------------------------------
SELECT
    p.UserId,
    p.TransactionId,
    COALESCE(
        NULLIF(cm.LastPackageId, 0),
        NULLIF(cm.FirstPackageId, 0),
        @BasePackageId
    ) AS PackageId,
    COALESCE(t.Amount, @BasePackagePrice) AS Amount,
    COALESCE(t.PaymentDate, cm.ActivatedAt, @Now) AS PurchasedAt
INTO #UppPlan
FROM @Phase1 p
INNER JOIN CMS.Transactions t ON t.Id = p.TransactionId AND t.IsDeleted = 0
LEFT JOIN CMS.ClubMemberships cm ON cm.UserId = p.UserId AND cm.IsDeleted = 0
WHERE NOT EXISTS (
    SELECT 1
    FROM CMS.UserPackagePurchases upp
    WHERE upp.UserId = p.UserId
      AND upp.IsDeleted = 0
      AND upp.TransactionId = p.TransactionId
);

DECLARE @ToCreate INT = (SELECT COUNT(*) FROM #UppPlan);
DECLARE @Skipped INT = (SELECT COUNT(*) FROM @Phase1) - @ToCreate;

PRINT CONCAT('UPP to create: ', @ToCreate, ' | Already linked (skip): ', @Skipped);

SELECT
    pl.UserId,
    u.Mobile,
    u.FirstName,
    u.LastName,
    pl.TransactionId,
    pl.PackageId,
    pl.Amount,
    pl.PurchasedAt,
    N'INSERT_UPP_MANUAL_3' AS Action
FROM #UppPlan pl
INNER JOIN CMS.Users u ON u.Id = pl.UserId AND u.IsDeleted = 0
ORDER BY pl.UserId;

------------------------------------------------------------
-- Insert UPP
------------------------------------------------------------
INSERT INTO CMS.UserPackagePurchases
(
    UserId, PackageId, PurchaseMethod, PurchasedAt, Amount,
    OrderId, TransactionId, Created, CreatedBy, LastModified, LastModifiedBy, IsDeleted
)
SELECT
    pl.UserId,
    pl.PackageId,
    3, -- Manual
    pl.PurchasedAt,
    pl.Amount,
    NULL,
    pl.TransactionId,
    @Now,
    NULL,
    @Now,
    NULL,
    0
FROM #UppPlan pl
WHERE pl.PackageId IS NOT NULL
  AND pl.Amount > 0;

PRINT CONCAT('UPP inserted: ', @@ROWCOUNT);

DROP TABLE #UppPlan;

------------------------------------------------------------
-- Verify
------------------------------------------------------------
SELECT
    p.UserId,
    u.Mobile,
    p.TransactionId,
    CASE WHEN upp.Id IS NOT NULL THEN N'OK' ELSE N'MISSING_UPP' END AS UppStatus,
    upp.Id AS UppId,
    upp.PurchaseMethod,
    upp.TransactionId AS UppTxId
FROM @Phase1 p
INNER JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0
LEFT JOIN CMS.UserPackagePurchases upp
    ON upp.UserId = p.UserId
   AND upp.IsDeleted = 0
   AND upp.TransactionId = p.TransactionId
ORDER BY p.UserId;

SELECT N'Missing UPP after run' AS CheckName, COUNT(*) AS Cnt
FROM @Phase1 p
WHERE NOT EXISTS (
    SELECT 1
    FROM CMS.UserPackagePurchases upp
    WHERE upp.UserId = p.UserId
      AND upp.IsDeleted = 0
      AND upp.TransactionId = p.TransactionId
);

ROLLBACK;
-- COMMIT;

PRINT 'Done (rolled back by default). Uncomment COMMIT when preview looks correct.';
