/*
  DIAGNOSTIC ONLY — no data changes (read-only)

  Trace WrongDaya→Manual FixUsers ledger via UserWalletHistory:
    WalletHistory → CreatedBy/LastModifiedBy (mobile) → User → Wallet
    → Transaction (RefrenceId / CreatedBy-as-TxId / Tx.CreatedBy mobile)
    → UPP / ManualPayment / PurchaseMethod

  Known IDs from manual CSV exports (UserWalletHistories*.csv, Transactions.csv):
    WH: 102-108,122,138-142,292-295,118-121,124,201
    Tx: 23-31,42-46,56-59,68,107-110

  RefrenceId=0 rule (ChargeUserWallets.sql):
    RefId = 'manualy' + original ChangeLogId. After id remap, WH.RefrenceId may be 0.
    For Ref=0 rows, assume Tx exists ONLY if CreatedBy is numeric AND that Tx has RefId manualy%.
    Do NOT infer Tx from mobile alone or from manualy{N} suffix alone.

  See also: 10-Diagnose_Manualy_Transaction_Map.sql

  Run on staging, review Verdict + RecommendedAction per user before any fix script.
*/

SET NOCOUNT ON;

DECLARE @FixUsers TABLE (UserId BIGINT PRIMARY KEY);
INSERT INTO @FixUsers (UserId) VALUES
(2),(7),(8),(9),(10),(11),(12),(13),(40),(41),(43),(45),(47),
(52),(58),(69),(71),(72),(74),(75),(87),(88),(89),(90),(91),(93),
(96),(99),(103),(105),(106),(111),(113),(115),(116),(119),(121),
(125),(130),(142),(162),(169),(170),(171),(172),(175),(176);

-- Known WalletHistory / Transaction ids from CSV exports (for cross-check)
DECLARE @KnownWh TABLE (WalletHistoryId BIGINT PRIMARY KEY);
INSERT INTO @KnownWh (WalletHistoryId) VALUES
(102),(103),(104),(105),(106),(107),(108),(122),
(138),(139),(140),(141),(142),
(292),(293),(294),(295),
(118),(119),(120),(121),(124),(201);

DECLARE @KnownTx TABLE (TransactionId BIGINT PRIMARY KEY);
INSERT INTO @KnownTx (TransactionId) VALUES
(23),(24),(25),(26),(28),(29),(30),(31),
(42),(43),(44),(45),(46),
(56),(57),(58),(59),(68),
(107),(108),(109),(110);

DECLARE @TargetUserCount INT = (SELECT COUNT(*) FROM @FixUsers);
PRINT CONCAT('FixUsers scope: ', @TargetUserCount);

------------------------------------------------------------
-- 1) WalletHistories found BY mobile in CreatedBy / LastModifiedBy
--    (starts from WH — user request)
------------------------------------------------------------
PRINT '=== 1) WalletHistory → User via CreatedBy/LastModifiedBy mobile ===';

SELECT
    h.Id AS WalletHistoryId,
    h.WalletId,
    h.RefrenceId AS WhRefrenceId,
    h.ChangeValue,
    h.ChangeDiscountValue,
    h.Created AS WhCreated,
    h.CreatedBy AS WhCreatedBy,
    h.LastModifiedBy AS WhLastModifiedBy,
    u.Id AS UserId,
    u.Mobile,
    u.FirstName,
    u.LastName,
    u.PackagePurchaseMethod AS UserMethod,
    CASE WHEN kwh.WalletHistoryId IS NOT NULL THEN 1 ELSE 0 END AS InKnownWhCsv,
    CASE
        WHEN u.Id IS NULL THEN N'NO_USER_FOR_MOBILE'
        WHEN f.UserId IS NULL THEN N'USER_NOT_IN_FIX_SCOPE'
        ELSE N'IN_FIX_SCOPE'
    END AS ScopeStatus
FROM CMS.UserWalletHistories h
LEFT JOIN CMS.Users u ON u.IsDeleted = 0
    AND u.Mobile IN (
        NULLIF(LTRIM(RTRIM(h.CreatedBy)), N''),
        NULLIF(LTRIM(RTRIM(h.LastModifiedBy)), N'')
    )
LEFT JOIN @FixUsers f ON f.UserId = u.Id
LEFT JOIN @KnownWh kwh ON kwh.WalletHistoryId = h.Id
WHERE h.IsDeleted = 0
  AND (
        (h.CreatedBy LIKE N'09%' AND LEN(h.CreatedBy) >= 10)
     OR (h.LastModifiedBy LIKE N'09%' AND LEN(h.LastModifiedBy) >= 10)
  )
ORDER BY h.Id;

------------------------------------------------------------
-- 2) All WalletHistories for FixUsers (via Wallet → User)
------------------------------------------------------------
PRINT '=== 2) All WalletHistory rows for FixUsers ===';

SELECT
    f.UserId,
    u.Mobile,
    u.FirstName,
    u.LastName,
    u.PackagePurchaseMethod AS UserMethod,
    w.Id AS WalletId,
    h.Id AS WalletHistoryId,
    h.RefrenceId AS WhRefrenceId,
    h.ChangeValue,
    h.ChangeDiscountValue,
    h.Created AS WhCreated,
    h.CreatedBy AS WhCreatedBy,
    h.LastModifiedBy AS WhLastModifiedBy,
    CASE WHEN kwh.WalletHistoryId IS NOT NULL THEN 1 ELSE 0 END AS InKnownWhCsv,
    CASE WHEN h.RefrenceId IS NULL OR h.RefrenceId = 0 THEN N'WH_NO_REF' ELSE N'WH_HAS_REF' END AS WhRefStatus
FROM @FixUsers f
INNER JOIN CMS.Users u ON u.Id = f.UserId AND u.IsDeleted = 0
INNER JOIN CMS.UserWallets w ON w.UserId = f.UserId AND w.IsDeleted = 0
INNER JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id AND h.IsDeleted = 0
LEFT JOIN @KnownWh kwh ON kwh.WalletHistoryId = h.Id
ORDER BY f.UserId, h.Id;

------------------------------------------------------------
-- 3) Per-user ledger verdict (WH + Tx + UPP)
------------------------------------------------------------
PRINT '=== 3) Per-user ledger verdict ===';

;WITH UserWh AS (
    SELECT
        f.UserId,
        COUNT(*) AS WalletHistoryCount,
        SUM(CASE WHEN h.RefrenceId IS NULL OR h.RefrenceId = 0 THEN 1 ELSE 0 END) AS WhMissingRefCount,
        SUM(CASE WHEN kwh.WalletHistoryId IS NOT NULL THEN 1 ELSE 0 END) AS KnownCsvWhCount,
        MAX(h.Id) AS LatestWhId,
        MAX(h.RefrenceId) AS LatestWhRefId
    FROM @FixUsers f
    INNER JOIN CMS.UserWallets w ON w.UserId = f.UserId AND w.IsDeleted = 0
    LEFT JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id AND h.IsDeleted = 0
    LEFT JOIN @KnownWh kwh ON kwh.WalletHistoryId = h.Id
    GROUP BY f.UserId
),
UserTxViaWh AS (
    SELECT
        uw.UserId,
        COUNT(DISTINCT t.Id) AS TxViaWhRefCount,
        MAX(t.Id) AS SampleTxViaWhRef
    FROM UserWh uw
    INNER JOIN CMS.UserWallets w ON w.UserId = uw.UserId AND w.IsDeleted = 0
    INNER JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id AND h.IsDeleted = 0
    INNER JOIN CMS.Transactions t ON t.Id = h.RefrenceId AND t.IsDeleted = 0
    GROUP BY uw.UserId
),
UserTxViaMobile AS (
    SELECT
        f.UserId,
        COUNT(DISTINCT t.Id) AS TxViaMobileCount,
        MAX(t.Id) AS SampleTxViaMobile
    FROM @FixUsers f
    INNER JOIN CMS.Users u ON u.Id = f.UserId AND u.IsDeleted = 0
    INNER JOIN CMS.Transactions t ON t.IsDeleted = 0
        AND (t.CreatedBy = u.Mobile OR t.LastModifiedBy = u.Mobile)
    GROUP BY f.UserId
),
UserTxViaCreatedByHint AS (
    -- WH.CreatedBy stores Tx Id when RefrenceId=0 failed to update (UserWalletHistories2.csv).
    -- Only count when hinted Tx exists AND is manualy% (may still be wrong user — verify mobile).
    SELECT
        f.UserId,
        COUNT(DISTINCT t.Id) AS TxViaWhCreatedByHintCount,
        MAX(t.Id) AS SampleTxViaHint
    FROM @FixUsers f
    INNER JOIN CMS.UserWallets w ON w.UserId = f.UserId AND w.IsDeleted = 0
    INNER JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id AND h.IsDeleted = 0
    INNER JOIN CMS.Transactions t ON t.Id = TRY_CAST(h.CreatedBy AS BIGINT)
        AND t.IsDeleted = 0 AND t.RefId LIKE N'manualy%'
    WHERE (h.RefrenceId IS NULL OR h.RefrenceId = 0)
      AND TRY_CAST(h.CreatedBy AS BIGINT) > 0
    GROUP BY f.UserId
),
UserTxViaManualyMobile AS (
    -- Informational only — NOT used alone for Ref=0 WH linking
    SELECT
        f.UserId,
        COUNT(DISTINCT t.Id) AS TxViaManualyMobileCount,
        MAX(t.Id) AS SampleManualyTxViaMobile
    FROM @FixUsers f
    INNER JOIN CMS.Users u ON u.Id = f.UserId AND u.IsDeleted = 0
    INNER JOIN CMS.Transactions t ON t.IsDeleted = 0
        AND t.RefId LIKE N'manualy%'
        AND u.Mobile IN (
            NULLIF(LTRIM(RTRIM(t.CreatedBy)), N''),
            NULLIF(LTRIM(RTRIM(t.LastModifiedBy)), N'')
        )
    GROUP BY f.UserId
),
UserUpp AS (
    SELECT
        f.UserId,
        COUNT(*) AS UppCount,
        SUM(CASE WHEN upp.PurchaseMethod = 1 THEN 1 ELSE 0 END) AS UppDayaCount,
        SUM(CASE WHEN upp.PurchaseMethod = 3 THEN 1 ELSE 0 END) AS UppManualCount,
        MAX(upp.TransactionId) AS LatestUppTxId
    FROM @FixUsers f
    LEFT JOIN CMS.UserPackagePurchases upp
        ON upp.UserId = f.UserId AND upp.IsDeleted = 0
    GROUP BY f.UserId
),
UserMp AS (
    SELECT
        f.UserId,
        COUNT(*) AS ManualPaymentCount,
        MAX(mp.TransactionId) AS LatestMpTxId
    FROM @FixUsers f
    LEFT JOIN CMS.ManualPayments mp
        ON mp.UserId = f.UserId AND mp.IsDeleted = 0
    GROUP BY f.UserId
)
SELECT *
FROM (
    SELECT
        f.UserId,
        u.Mobile,
        u.FirstName,
        u.LastName,
        u.PackagePurchaseMethod AS UserMethod,
        ISNULL(uwh.WalletHistoryCount, 0) AS WalletHistoryCount,
        ISNULL(uwh.WhMissingRefCount, 0) AS WhMissingRefCount,
        ISNULL(uwh.KnownCsvWhCount, 0) AS KnownCsvWhCount,
        uwh.LatestWhId,
        uwh.LatestWhRefId,
        ISNULL(utw.TxViaWhRefCount, 0) AS TxViaWhRefCount,
        utw.SampleTxViaWhRef,
        ISNULL(utm.TxViaMobileCount, 0) AS TxViaMobileCount,
        utm.SampleTxViaMobile,
        ISNULL(uth.TxViaWhCreatedByHintCount, 0) AS TxViaWhCreatedByHintCount,
        uth.SampleTxViaHint,
        ISNULL(utmm.TxViaManualyMobileCount, 0) AS TxViaManualyMobileCount,
        utmm.SampleManualyTxViaMobile,
        ISNULL(uu.UppCount, 0) AS UppCount,
        ISNULL(uu.UppDayaCount, 0) AS UppDayaCount,
        uu.LatestUppTxId,
        ISNULL(ump.ManualPaymentCount, 0) AS ManualPaymentCount,
        ump.LatestMpTxId,
        CASE
            WHEN ISNULL(uwh.WalletHistoryCount, 0) = 0 THEN N'NO_WALLET_HISTORY'
            WHEN ISNULL(uwh.WhMissingRefCount, 0) > 0
                 AND ISNULL(uth.TxViaWhCreatedByHintCount, 0) > 0 THEN N'WH_REF_BROKEN_FIX_VIA_CREATEDBY_HINT'
            WHEN ISNULL(uwh.WhMissingRefCount, 0) > 0
                 AND ISNULL(utmm.TxViaManualyMobileCount, 0) > 0 THEN N'WH_REF_BROKEN_MANUALY_TX_BY_MOBILE_REVIEW'
            WHEN ISNULL(uwh.WhMissingRefCount, 0) > 0 THEN N'WH_REF_BROKEN_NO_TX_HINT'
            WHEN ISNULL(utw.TxViaWhRefCount, 0) > 0
                 AND ISNULL(uu.UppCount, 0) = 0 THEN N'HAS_WH+TX_NEED_UPP'
            WHEN ISNULL(utw.TxViaWhRefCount, 0) > 0
                 AND ISNULL(uu.UppDayaCount, 0) > 0 THEN N'HAS_WH+TX_UPP_DAYA_FIX_METHOD'
            WHEN ISNULL(utw.TxViaWhRefCount, 0) > 0 THEN N'OK_WH+TX'
            WHEN ISNULL(utm.TxViaMobileCount, 0) > 0 THEN N'TX_BY_MOBILE_WH_LINK_UNCLEAR'
            ELSE N'NEEDS_MANUAL_REVIEW'
        END AS Verdict,
        CASE
            WHEN ISNULL(uwh.WalletHistoryCount, 0) = 0 THEN N'Create WH+Tx+UPP (or find hidden WH by mobile)'
            WHEN ISNULL(uwh.WhMissingRefCount, 0) > 0
                 AND ISNULL(uth.TxViaWhCreatedByHintCount, 0) > 0 THEN N'Link WH.RefrenceId to manualy Tx from CreatedBy hint only'
            WHEN ISNULL(uwh.WhMissingRefCount, 0) > 0
                 AND ISNULL(utmm.TxViaManualyMobileCount, 0) > 0 THEN N'manualy Tx exists by mobile but WH hint missing — manual review'
            WHEN ISNULL(uwh.WhMissingRefCount, 0) > 0 THEN N'No Tx hint — do NOT assume Tx exists; review charge log'
            WHEN ISNULL(utw.TxViaWhRefCount, 0) > 0 AND ISNULL(uu.UppCount, 0) = 0 THEN N'Create UPP Manual(3) reusing Tx'
            WHEN ISNULL(uu.UppDayaCount, 0) > 0 OR u.PackagePurchaseMethod = 1 THEN N'Fix PurchaseMethod 1→3 only'
            ELSE N'Likely OK — verify PurchaseMethod'
        END AS RecommendedAction
    FROM @FixUsers f
    INNER JOIN CMS.Users u ON u.Id = f.UserId AND u.IsDeleted = 0
    LEFT JOIN UserWh uwh ON uwh.UserId = f.UserId
    LEFT JOIN UserTxViaWh utw ON utw.UserId = f.UserId
    LEFT JOIN UserTxViaMobile utm ON utm.UserId = f.UserId
    LEFT JOIN UserTxViaCreatedByHint uth ON uth.UserId = f.UserId
    LEFT JOIN UserTxViaManualyMobile utmm ON utmm.UserId = f.UserId
    LEFT JOIN UserUpp uu ON uu.UserId = f.UserId
    LEFT JOIN UserMp ump ON ump.UserId = f.UserId
) q
ORDER BY
    CASE q.Verdict
        WHEN N'OK_WH+TX' THEN 9
        WHEN N'HAS_WH+TX_UPP_DAYA_FIX_METHOD' THEN 8
        ELSE 1
    END,
    q.UserId;

------------------------------------------------------------
-- 4) Summary counts by Verdict
------------------------------------------------------------
PRINT '=== 4) Summary by Verdict ===';

;WITH PerUser AS (
    SELECT
        f.UserId,
        u.PackagePurchaseMethod AS UserMethod,
        ISNULL(uwh.Cnt, 0) AS WhCnt,
        ISNULL(uwh.BadRefCnt, 0) AS WhBadRefCnt,
        ISNULL(utw.Cnt, 0) AS TxViaWhCnt,
        ISNULL(utm.Cnt, 0) AS TxViaMobileCnt,
        ISNULL(uth.Cnt, 0) AS TxViaHintCnt,
        ISNULL(uu.Cnt, 0) AS UppCnt
    FROM @FixUsers f
    INNER JOIN CMS.Users u ON u.Id = f.UserId AND u.IsDeleted = 0
    OUTER APPLY (
        SELECT COUNT(*) AS Cnt,
               SUM(CASE WHEN h.RefrenceId IS NULL OR h.RefrenceId = 0 THEN 1 ELSE 0 END) AS BadRefCnt
        FROM CMS.UserWallets w
        INNER JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id AND h.IsDeleted = 0
        WHERE w.UserId = f.UserId AND w.IsDeleted = 0
    ) uwh
    OUTER APPLY (
        SELECT COUNT(DISTINCT t.Id) AS Cnt
        FROM CMS.UserWallets w
        INNER JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id AND h.IsDeleted = 0
        INNER JOIN CMS.Transactions t ON t.Id = h.RefrenceId AND t.IsDeleted = 0
        WHERE w.UserId = f.UserId AND w.IsDeleted = 0
    ) utw
    OUTER APPLY (
        SELECT COUNT(DISTINCT t.Id) AS Cnt
        FROM CMS.Transactions t
        WHERE t.IsDeleted = 0
          AND (t.CreatedBy = u.Mobile OR t.LastModifiedBy = u.Mobile)
    ) utm
    OUTER APPLY (
        SELECT COUNT(DISTINCT t.Id) AS Cnt
        FROM CMS.UserWallets w
        INNER JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id AND h.IsDeleted = 0
        INNER JOIN CMS.Transactions t ON t.Id = TRY_CAST(h.CreatedBy AS BIGINT)
            AND t.IsDeleted = 0 AND t.RefId LIKE N'manualy%'
        WHERE w.UserId = f.UserId AND w.IsDeleted = 0
          AND (h.RefrenceId IS NULL OR h.RefrenceId = 0)
          AND TRY_CAST(h.CreatedBy AS BIGINT) > 0
    ) uth
    OUTER APPLY (
        SELECT COUNT(*) AS Cnt
        FROM CMS.UserPackagePurchases upp
        WHERE upp.UserId = f.UserId AND upp.IsDeleted = 0
    ) uu
),
Verdicts AS (
    SELECT
        UserId,
        CASE
            WHEN WhCnt = 0 THEN N'NO_WALLET_HISTORY'
            WHEN WhBadRefCnt > 0 AND TxViaHintCnt > 0 THEN N'WH_REF_BROKEN_FIX_VIA_CREATEDBY_HINT'
            WHEN WhBadRefCnt > 0 THEN N'WH_REF_BROKEN_NO_TX_HINT'
            WHEN TxViaWhCnt > 0 AND UppCnt = 0 THEN N'HAS_WH+TX_NEED_UPP'
            WHEN TxViaWhCnt > 0 THEN N'OK_WH+TX'
            WHEN TxViaMobileCnt > 0 THEN N'TX_BY_MOBILE_WH_LINK_UNCLEAR'
            ELSE N'NEEDS_MANUAL_REVIEW'
        END AS Verdict
    FROM PerUser
)
SELECT Verdict, COUNT(*) AS UserCount
FROM Verdicts
GROUP BY Verdict
ORDER BY UserCount DESC;

------------------------------------------------------------
-- 5) Known CSV Tx ids — exist in DB? linked to WH/UPP?
------------------------------------------------------------
PRINT '=== 5) Known Transaction IDs from CSV ===';

SELECT
    kt.TransactionId,
    CASE WHEN t.Id IS NULL THEN N'MISSING_IN_DB' ELSE N'EXISTS' END AS TxStatus,
    t.Amount,
    t.Description,
    t.RefId,
    t.CreatedBy AS TxCreatedBy,
    t.LastModifiedBy AS TxLastModifiedBy,
    u.Id AS UserByMobile,
    u.Mobile,
    h.Id AS LinkedWalletHistoryId,
    h.WalletId,
    h.RefrenceId AS WhRefrenceId,
    upp.UserId AS UppUserId,
    upp.PurchaseMethod AS UppMethod
FROM @KnownTx kt
LEFT JOIN CMS.Transactions t ON t.Id = kt.TransactionId
LEFT JOIN CMS.Users u ON u.IsDeleted = 0
    AND u.Mobile IN (NULLIF(t.CreatedBy, N''), NULLIF(t.LastModifiedBy, N''))
LEFT JOIN CMS.UserWalletHistories h ON h.IsDeleted = 0 AND h.RefrenceId = kt.TransactionId
LEFT JOIN CMS.UserPackagePurchases upp ON upp.IsDeleted = 0 AND upp.TransactionId = kt.TransactionId
ORDER BY kt.TransactionId;

------------------------------------------------------------
-- 6) Known CSV WH ids — RefrenceId vs CreatedBy hint vs mobile
------------------------------------------------------------
PRINT '=== 6) Known WalletHistory IDs from CSV ===';

SELECT
    kw.WalletHistoryId,
    h.WalletId,
    h.RefrenceId AS WhRefrenceId,
    h.ChangeValue,
    h.CreatedBy AS WhCreatedBy,
    h.LastModifiedBy AS WhLastModifiedBy,
    w.UserId AS WalletUserId,
    u.Mobile AS WalletUserMobile,
    u_by_mobile.Id AS UserByWhMobile,
    u_by_mobile.Mobile AS MatchedMobile,
    t_ref.Id AS TxByRefrenceId,
    t_ref.Description AS TxByRefDescription,
    t_hint.Id AS TxByCreatedByHint,
    t_hint.RefId AS TxByHintRefId,
    t_hint.Description AS TxByHintDescription,
    TRY_CAST(
        SUBSTRING(t_hint.RefId, LEN(N'manualy') + 1, 20)
        AS BIGINT
    ) AS ManualyOriginalChangeLogId,
    CASE
        WHEN h.Id IS NULL THEN N'WH_MISSING_IN_DB'
        WHEN t_ref.Id IS NOT NULL AND t_ref.RefId LIKE N'manualy%' THEN N'WH_LINKED_TO_MANUALY_TX'
        WHEN t_ref.Id IS NOT NULL THEN N'WH_LINKED_TO_OTHER_TX'
        WHEN t_hint.Id IS NOT NULL AND t_hint.RefId LIKE N'manualy%' THEN N'WH_REF_BROKEN_USE_CREATEDBY_HINT'
        WHEN TRY_CAST(h.CreatedBy AS BIGINT) > 0 AND t_hint.Id IS NULL THEN N'WH_HINT_TX_MISSING'
        WHEN u_by_mobile.Id IS NOT NULL THEN N'WH_MOBILE_ONLY_NO_AUTO_LINK'
        ELSE N'WH_ORPHAN_REVIEW'
    END AS WhLinkStatus
FROM @KnownWh kw
LEFT JOIN CMS.UserWalletHistories h ON h.Id = kw.WalletHistoryId AND h.IsDeleted = 0
LEFT JOIN CMS.UserWallets w ON w.Id = h.WalletId AND w.IsDeleted = 0
LEFT JOIN CMS.Users u ON u.Id = w.UserId AND u.IsDeleted = 0
LEFT JOIN CMS.Users u_by_mobile ON u_by_mobile.IsDeleted = 0
    AND u_by_mobile.Mobile IN (
        NULLIF(LTRIM(RTRIM(h.CreatedBy)), N''),
        NULLIF(LTRIM(RTRIM(h.LastModifiedBy)), N'')
    )
LEFT JOIN CMS.Transactions t_ref ON t_ref.Id = h.RefrenceId AND t_ref.IsDeleted = 0
LEFT JOIN CMS.Transactions t_hint ON t_hint.Id = TRY_CAST(h.CreatedBy AS BIGINT) AND t_hint.IsDeleted = 0
ORDER BY kw.WalletHistoryId;

PRINT 'Done (diagnostic only — no changes).';
