import requests
from flask import Flask, request, render_template_string, jsonify
import json
import os
import hmac
import hashlib
import base64
import mysql.connector
from datetime import datetime
from dotenv import load_dotenv
from flask import redirect, session, url_for
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# Initialize Flask Application
app = Flask(__name__)
print("--- INTERAC SERVER v2.0 (Multi-Store) ---")

# Load environment variables from .env file
load_dotenv(override=True)

# --- MAIL CONFIGURATION ---
MAIL_SERVER    = os.getenv("MAIL_SERVER", "smtp.mandrillapp.com")
MAIL_PORT      = int(os.getenv("MAIL_PORT", 587))
MAIL_USERNAME  = os.getenv("MAIL_USERNAME")
MAIL_PASSWORD  = os.getenv("MAIL_PASSWORD")
SMTP_FROM_EMAIL = os.getenv("SMTP_FROM_EMAIL", "no-reply@emtwerx.com")

# --- CONFIGURATION & CREDENTIALS ---
ZUM_USERNAME = os.getenv("ZUM_USERNAME")
ZUM_PASSWORD = os.getenv("ZUM_PASSWORD")
ZUM_ENV = os.getenv("ZUM_ENV")
ZUM_WEBHOOK_SECRET = os.getenv("ZUM_WEBHOOK_SECRET")
ZUM_WALLET_ID = os.getenv("ZUM_WALLET_ID")
ZUM_SECONDARY_WEBHOOK_URL = os.getenv("ZUM_SECONDARY_WEBHOOK_URL")

# --- DATABASE CONFIGURATION ---
DB_HOST = os.getenv("DB_HOST", "localhost")
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_NAME = os.getenv("DB_NAME")
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin123")

# Shopify App Credentials (from Partner Dashboard)
SHOPIFY_API_KEY = os.getenv("SHOPIFY_API_KEY")
SHOPIFY_API_SECRET = os.getenv("SHOPIFY_API_SECRET")
SHOPIFY_REDIRECT_URI = os.getenv("SHOPIFY_REDIRECT_URI", "https://conclude-party-paralyses.ngrok-free.dev/auth/callback")
SHOPIFY_SCOPES = "read_orders,write_orders,read_customers"

app.secret_key = os.getenv("FLASK_SECRET_KEY", "super-secret-key-123")


def verify_shopify_hmac(params, secret):
    """Verifies the HMAC signature from Shopify for security."""
    hmac_val = params.get('hmac')
    if not hmac_val:
        return False

    # Sort and join all parameters except hmac
    sorted_params = sorted([(k, v) for k, v in params.items() if k != 'hmac'])
    query_string = "&".join([f"{k}={v}" for k, v in sorted_params])

    hash_val = hmac.new(
        secret.encode('utf-8'),
        query_string.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(hash_val, hmac_val)


def get_db_connection():
    """Establishes and returns a MySQL database connection."""
    return mysql.connector.connect(
        host=DB_HOST,
        user=DB_USER,
        password=DB_PASSWORD,
        database=DB_NAME
    )


def init_db():
    """Initializes the database tables if they don't exist."""
    try:
        conn = get_db_connection()
        cursor = conn.cursor()

        # Domains table (stores allowed shops and their per-store tokens)
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS domains (
                id INT AUTO_INCREMENT PRIMARY KEY,
                domain VARCHAR(255) UNIQUE NOT NULL,
                access_token VARCHAR(255),
                status VARCHAR(50) DEFAULT 'active',
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        """)

        # Migration: add access_token column if it doesn't exist yet
        try:
            cursor.execute("ALTER TABLE domains ADD COLUMN access_token VARCHAR(255)")
            print("✅ Migrated: Added 'access_token' column to domains table.")
        except mysql.connector.Error as err:
            if err.errno == 1060:  # Column already exists — safe to ignore
                pass
            else:
                raise

        conn.commit()
        cursor.close()
        conn.close()
        print("✅ Database Initialized (MySQL)")
    except Exception as e:
        print(f"❌ Database Initialization Error: {e}")


init_db()


# --- API ENVIRONMENT SWITCHER ---
ZUM_API_URL = (
    "https://api-sandbox.zumrails.com/api"
    if ZUM_ENV == "test"
    else "https://api-app.zumrails.com/api"
)


# --- SHOPIFY OAUTH ROUTES ---

@app.route('/auth')
def auth():
    """Starts the OAuth installation flow."""
    shop = request.args.get('shop')
    if not shop:
        return "Missing shop parameter", 400

    # Build the installation URL
    install_url = (
        f"https://{shop}/admin/oauth/authorize?"
        f"client_id={SHOPIFY_API_KEY}&"
        f"scope={SHOPIFY_SCOPES}&"
        f"redirect_uri={SHOPIFY_REDIRECT_URI}"
    )
    print(f"🔗 Redirecting to Shopify Auth: {install_url}")
    return redirect(install_url)


@app.route('/auth/callback')
def auth_callback():
    """Handles the callback from Shopify and exchanges the code for a token."""
    params = request.args.to_dict()
    shop = params.get('shop')
    code = params.get('code')

    # 1. Verify Security (HMAC)
    if not verify_shopify_hmac(params, SHOPIFY_API_SECRET):
        print("❌ SECURITY ALERT: Invalid HMAC in OAuth callback!")
        return "Invalid signature", 401

    # 2. Exchange code for permanent Access Token
    token_url = f"https://{shop}/admin/oauth/access_token"
    payload = {
        "client_id": SHOPIFY_API_KEY,
        "client_secret": SHOPIFY_API_SECRET,
        "code": code
    }

    try:
        resp = requests.post(token_url, json=payload)
        data = resp.json()
        access_token = data.get('access_token')

        if access_token:
            # 3. Save to database
            conn = get_db_connection()
            cursor = conn.cursor()
            cursor.execute(
                "INSERT INTO domains (domain, access_token, status) VALUES (%s, %s, 'active') "
                "ON DUPLICATE KEY UPDATE access_token = VALUES(access_token), status = 'active'",
                (shop, access_token)
            )
            conn.commit()
            cursor.close()
            conn.close()
            print(f"✅ App successfully installed on {shop}. Token saved.")
            return f"<h1>Installation Successful!</h1><p>The app is now linked to <b>{shop}</b>. You can close this window.</p>"
        else:
            print(f"❌ Failed to get access token: {data}")
            return f"Error: {data.get('error_description', 'Unknown error')}", 400

    except Exception as e:
        print(f"❌ OAuth Exchange Error: {e}")
        return "Server Error during authentication", 500


def get_store_credentials(shop_domain):
    """
    Returns (access_token, status) for a given shop domain from the DB.
    Falls back to the global env-var token if no per-store token is stored.
    """
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute(
            "SELECT status, access_token FROM domains WHERE domain = %s",
            (shop_domain,)
        )
        row = cursor.fetchone()
        cursor.close()
        conn.close()

        if not row:
            return None, None  # Store not registered

        token = row.get("access_token") or SHOPIFY_ACCESS_TOKEN  # per-store token or fallback
        return token, row["status"]

    except Exception as e:
        print(f"⚠️ get_store_credentials error: {e}")
        return None, None


def get_order_details(order_id, shop_domain=None, access_token=None):
    """
    Fetches verified order details from Shopify Admin API.
    Returns (first_name, last_name, verified_amount).
    Never trust URL params for amount — always verify server-side.
    """
    target_domain = shop_domain or SHOPIFY_DOMAIN
    token = access_token or SHOPIFY_ACCESS_TOKEN

    if not order_id or not token or not target_domain:
        return "", "", None

    try:
        url = f"https://{target_domain}/admin/api/2024-01/orders/{order_id}.json"
        headers = {"X-Shopify-Access-Token": token}
        resp = requests.get(url, headers=headers, timeout=5)

        print(f"🔍 Shopify API [{resp.status_code}] for order {order_id} on {target_domain}")

        if resp.status_code != 200:
            print(f"⚠️ Shopify fetch failed: {resp.text[:200]}")
            return "", "", None

        order = resp.json().get("order", {})

        # Always use presentment_money (the actual CAD amount the customer sees)
        verified_amount = (
            order.get("total_price_set", {})
                 .get("presentment_money", {})
                 .get("amount")
        )
        if not verified_amount or float(verified_amount) == 0:
            verified_amount = order.get("total_price")
            print(f"⚠️ Fell back to total_price: {verified_amount}")

        # Name: billing → shipping → customer
        for src in [
            order.get("billing_address"),
            order.get("shipping_address"),
            order.get("customer")
        ]:
            if src:
                first = (src.get("first_name") or "").strip()
                last  = (src.get("last_name")  or "").strip()
                if first or last:
                    return first, last, verified_amount

        return "", "", verified_amount

    except Exception as e:
        print(f"⚠️ get_order_details error: {e}")
        return "", "", None


def verify_zum_signature(payload_bytes, signature):
    """Verifies that the webhook really came from Zum Rails."""
    if not ZUM_WEBHOOK_SECRET:
        return True  # Skip if secret not configured (dev mode)

    expected_signature = base64.b64encode(
        hmac.new(
            ZUM_WEBHOOK_SECRET.strip().encode("utf-8"),
            payload_bytes,
            hashlib.sha256
        ).digest()
    ).decode("utf-8")

    return hmac.compare_digest(expected_signature, signature)


@app.route("/", methods=["GET", "POST"])
def test():
    return "Working"


@app.route("/start-payment", methods=["GET", "POST"])
def start_payment():
    # --- STEP 1: Extract data from URL ---
    order_id    = request.values.get("order_id")
    amount      = request.values.get("amount")   # untrusted — overwritten below
    email       = request.values.get("email")
    shop_domain = request.values.get("shop")
    first_name  = request.values.get("first_name", "").strip()
    last_name   = request.values.get("last_name",  "").strip()

    # --- STEP 2: Domain validation + fetch per-store token ---
    store_token, store_status = get_store_credentials(shop_domain)

    if store_token is None:
        return f"""
        <div style="font-family:sans-serif;text-align:center;padding:50px;">
            <h2 style="color:#dc3545;">Store Not Registered</h2>
            <p>The store <b>{shop_domain}</b> is not authorized to use this payment gateway.</p>
            <p>Please contact <b>FintechWerx</b> support for registration.</p>
        </div>"""

    if store_status != "active":
        return """
        <div style="font-family:sans-serif;text-align:center;padding:50px;">
            <h2 style="color:#6c757d;">Account Inactive</h2>
            <p>Your Interac payment service is currently <b>inactive</b>.</p>
            <p>Please contact FintechWerx to reactivate your store.</p>
        </div>"""

    # --- STEP 3: Verify amount + fetch names from Shopify (server-side, correct token) ---
    api_first, api_last, verified_amount = get_order_details(
        order_id, shop_domain, store_token
    )

    if verified_amount:
        amount = verified_amount
        print(f"✅ Amount verified from Shopify: ${amount}")
    else:
        print(f"🚫 Order {order_id} not found on {shop_domain}. Blocking request.")
        return """
        <div style="font-family:sans-serif;text-align:center;padding:60px 30px;">
            <h2 style="color:#dc3545;">Invalid Payment Link</h2>
            <p style="color:#555;max-width:400px;margin:0 auto;">
                This payment link is invalid or has expired.<br>
                Please return to the store and use the original link from your order confirmation.
            </p>
        </div>
        """

    if api_first and not first_name:
        first_name = api_first
    if api_last and not last_name:
        last_name = api_last

    # --- STEP 4: Seamless mode ---
   

    # --- STEP 5: Fallback form (POST submission) ---
    if request.method == "POST":
        email      = request.form.get("email")
        first_name = request.form.get("first_name", "").strip()
        last_name  = request.form.get("last_name",  "").strip()
        return process_zum_transaction(
            order_id, amount, email, shop_domain, first_name, last_name
        )

    # --- STEP 6: Render form ---
    if first_name or last_name:
        name_section = f"""
        <div style="display:flex;gap:10px;margin-bottom:15px;">
            <div style="flex:1;">
                <label style="display:block;margin-bottom:5px;font-size:13px;color:#555;">First Name</label>
                <input type="text" value="{first_name}" disabled
                       style="width:100%;padding:10px;box-sizing:border-box;background:#f5f5f5;
                              border:1px solid #ddd;border-radius:4px;color:#333;cursor:not-allowed;">
            </div>
            <div style="flex:1;">
                <label style="display:block;margin-bottom:5px;font-size:13px;color:#555;">Last Name</label>
                <input type="text" value="{last_name}" disabled
                       style="width:100%;padding:10px;box-sizing:border-box;background:#f5f5f5;
                              border:1px solid #ddd;border-radius:4px;color:#333;cursor:not-allowed;">
            </div>
        </div>
        <input type="hidden" name="first_name" value="{first_name}">
        <input type="hidden" name="last_name"  value="{last_name}">
        <p style="font-size:12px;color:#555;margin-top:-10px;margin-bottom:15px;background:#fff8e1;
                  border-left:3px solid #FFD100;padding:8px 10px;border-radius:4px;">
            ⚠️ <strong>Important:</strong> The name above must exactly match the name registered
            with your bank for Interac e-Transfer. Mismatched names may result in payment delays or rejection.
        </p>"""
    else:
        name_section = """
        <div style="display:flex;gap:10px;margin-bottom:15px;">
            <div style="flex:1;">
                <label style="display:block;margin-bottom:5px;font-size:13px;color:#555;">First Name</label>
                <input type="text" name="first_name" required placeholder="John"
                       style="width:100%;padding:10px;box-sizing:border-box;border:1px solid #ddd;border-radius:4px;">
            </div>
            <div style="flex:1;">
                <label style="display:block;margin-bottom:5px;font-size:13px;color:#555;">Last Name</label>
                <input type="text" name="last_name" required placeholder="Smith"
                       style="width:100%;padding:10px;box-sizing:border-box;border:1px solid #ddd;border-radius:4px;">
            </div>
        </div>"""

    return f"""
    <div style="font-family:sans-serif;max-width:420px;margin:50px auto;padding:30px;
                border:1px solid #ddd;border-radius:10px;box-shadow:0 2px 12px rgba(0,0,0,0.08);">
        <h2 style="text-align:center;margin-top:0;">Interac Payment</h2>
        <p style="text-align:center;color:#444;">Order <b>#{order_id}</b> &nbsp;|&nbsp; Total: <b>${amount}</b></p>
        <hr style="border:none;border-top:1px solid #eee;margin-bottom:20px;">
        <p style="color:#666;font-size:14px;margin-bottom:20px;">
            We couldn't detect your email automatically. Please enter it below to receive the Interac payment request.
        </p>
        <form method="POST">
            <input type="hidden" name="order_id" value="{order_id}">
            <input type="hidden" name="amount"   value="{amount}">
            <input type="hidden" name="shop"     value="{shop_domain}">
            {name_section}
            <label style="display:block;margin-bottom:5px;font-size:13px;color:#555;">Email Address</label>
            <input type="email" name="email" required placeholder="name@example.com"
                   style="width:100%;padding:10px;margin-bottom:20px;box-sizing:border-box;
                          border:1px solid #ddd;border-radius:4px;">
            <button type="submit"
                    style="width:100%;padding:13px;background:#FFD100;border:none;
                           border-radius:6px;font-weight:bold;font-size:15px;cursor:pointer;">
                Send Interac Request
            </button>
        </form>
    </div>"""

def send_interac_email(to_email, amount, comment, payment_url):
    """
    Sends the Interac payment request email to the customer
    using the HTML template via Mandrill SMTP.
    """
    try:
        # Load and fill the HTML template
        html_body = open("email_template.html").read()
        html_body = (
            html_body
            .replace("{{amount}}", str(amount))
            .replace("{{Comment}}", str(comment))
            .replace("{{payment_url}}", str(payment_url))
        )

        msg = MIMEMultipart("alternative")
        msg["Subject"] = f"Your Interac Payment Request – ${amount}"
        msg["From"]    = f"FintechWerx <{SMTP_FROM_EMAIL}>"
        msg["To"]      = to_email

        msg.attach(MIMEText(html_body, "html"))

        with smtplib.SMTP(MAIL_SERVER, MAIL_PORT) as server:
            server.ehlo()
            server.starttls()
            server.login(MAIL_USERNAME, MAIL_PASSWORD)
            server.sendmail(SMTP_FROM_EMAIL, to_email, msg.as_string())

        print(f"Email sent to {to_email} with payment URL: {payment_url}")
        return True

    except Exception as e:
        print(f"Email send failed: {e}")
        return False

def process_zum_transaction(order_id, amount, email, shop_domain=None, first_name="", last_name=""):
    """Authenticates with Zum Rails and sends the Interac payment request."""
    print(f"🚀 Sending Request to: {email} for ${amount}")

    short_memo = str(order_id)[-15:]
    zum_first = first_name if first_name else email.split("@")[0]
    zum_last  = last_name  if last_name  else "Shopify"

    try:
        # A. Authentication
        auth_response = requests.post(f"{ZUM_API_URL}/authorize", json={
            "Username": ZUM_USERNAME,
            "Password": ZUM_PASSWORD
        })

        if auth_response.status_code != 200:
            return f"<h3>Auth Error</h3><p>{auth_response.text}</p>"

        token = auth_response.json().get("result", {}).get("Token")

        # B. Send Transaction
        headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}

        payload = {
            "ZumRailsType": "AccountsReceivable",
            "TransactionMethod": "Interac",
            "Amount": float(amount),
            "Memo": short_memo,
            # shop_domain stored in Comment so webhook can look up the right store token
            "Comment": f"Shopify Order #{order_id} | Store: {shop_domain}",
            "InteracNotificationChannel": "email",
            "WalletId": ZUM_WALLET_ID,
            "User": {
                "FirstName": zum_first,
                "LastName": zum_last,
                "Email": email
            }
        }

        response = requests.post(f"{ZUM_API_URL}/transaction", json=payload, headers=headers)
        result = response.json()
        print("DEBUG RESPONSE:", result)

        if response.status_code == 200 and not result.get("IsError"):
            interac_url = result.get("result", {}).get("InteracUrl")

            if interac_url:
                # Build the comment shown in the email body
                email_comment = f"Shopify Order #{order_id} via {shop_domain}"

                email_sent = send_interac_email(
                    to_email=email,
                    amount=amount,
                    comment=email_comment,
                    payment_url=interac_url
                )

                if email_sent:
                    return redirect(interac_url)
                else:
                    # Email failed — fall back to redirect so customer isn't stuck
                    print("⚠️ Email failed — falling back to direct redirect")
                    return redirect(interac_url)

            # No InteracUrl in response (shouldn't happen in production)
            return f"""
            <div style="font-family:sans-serif;text-align:center;padding:50px;">
                <h1 style="color:#28a745;">✓ Request Sent!</h1>
                <p>We sent a payment request for <b>${amount}</b>.</p>
            </div>
            """
        else:
            error_msg = (
                result.get("responseException", {}).get("exceptionMessage")
                or str(result.get("errors") or result.get("Message"))
            )
            return f"<h3>Transaction Failed: {error_msg}</h3>"

    except Exception as e:
        return f"<h3>Server Error: {str(e)}</h3>"


# ---------------------------------------------------------------------------
# WEBHOOK
# ---------------------------------------------------------------------------

def _parse_shop_from_comment(comment):
    """Extracts shop domain from Comment field: 'Shopify Order #X | Store: domain'"""
    if comment and "Store:" in comment:
        return comment.split("Store:")[-1].strip()
    return None


def _get_token_for_shop(shop_domain):
    """Returns the access token for a shop domain (DB first, fallback to env var)."""
    if not shop_domain:
        return SHOPIFY_ACCESS_TOKEN
    token, _ = get_store_credentials(shop_domain)
    return token or SHOPIFY_ACCESS_TOKEN


@app.route("/webhook", methods=["POST"])
def webhook():
    # --- Security: Verify Signature ---
    signature = request.headers.get("zumrails-signature")
    if not signature or not verify_zum_signature(request.data, signature):
        print("❌ SECURITY ALERT: Invalid Signature Received!")
        return jsonify({"message": "Invalid Signature"}), 401

    data = request.json
    print("\n🔔 WEBHOOK RECEIVED!")

    # --- Data Forwarding ---
    destinations = [
        {"name": "Legacy PHP", "url": "https://payments.fintechwerx.com/order/zumrails/postback.php"},
        {"name": "New Sandbox", "url": ZUM_SECONDARY_WEBHOOK_URL}
    ]

    for dest in destinations:
        if not dest["url"]:
            continue
        try:
            print(f"➡️ Forwarding to {dest['name']}: {dest['url']}...")
            f_headers = {"zumrails-signature": signature, "Content-Type": "application/json"}
            fwd = requests.post(dest["url"], json=data, headers=f_headers, timeout=5)
            print(f"✅ {dest['name']} Status: {fwd.status_code}")
        except Exception as e:
            print(f"⚠️ Failed to forward to {dest['name']}: {e}")

    # --- Logging ---
    try:
        with open("webhook_logs.json", "a") as f:
            json.dump(data, f, indent=4)
            f.write("\n,\n")
        print("📁 Saved to webhook_logs.json")
    except Exception as e:
        print(f"Error saving log: {e}")

    # --- Parse Data ---
    inner_data = data.get("Data", {})
    event_type = data.get("Event")
    status     = inner_data.get("TransactionStatus")
    comment    = inner_data.get("Comment", "")

    print(f"🔎 Status: {status} | Event: {event_type}")

    # Identify which store this transaction belongs to
    shop_domain  = _parse_shop_from_comment(comment)
    store_token  = _get_token_for_shop(shop_domain)
    target_domain = shop_domain or SHOPIFY_DOMAIN

    print(f"🏪 Shop: {target_domain}")

    # --- Status Handling ---
    if event_type == "Succeeded" or status == "Completed":
        order_id       = inner_data.get("Memo")
        amount         = inner_data.get("Amount")
        transaction_id = inner_data.get("Id")

        if order_id:
            print(f"✅ Payment Succeeded for Order #{order_id}. Updating Shopify...")
            mark_shopify_order_paid(order_id, amount, transaction_id, target_domain, store_token)
        else:
            print("⚠️ Payment completed, but Order ID (Memo) was missing.")

    elif event_type == "Failed" or status in ["Failed", "Rejected", "Error"]:
        reason   = inner_data.get("FailedTransactionEvent") or "Unknown Error"
        order_id = inner_data.get("Memo")
        amount   = inner_data.get("Amount")

        print(f"❌ Payment FAILED for Order #{order_id} | Reason: {reason}")

        if order_id:
            mark_shopify_order_failed(order_id, amount, reason, target_domain, store_token)

    else:
        print(f"ℹ️  Transaction is in state: {status} (Ignored)")

    return jsonify({"message": "Received"}), 200


def mark_shopify_order_paid(order_id, amount, transaction_id, shop_domain=None, access_token=None):
    """Updates Shopify Order to 'Paid' using the correct per-store credentials."""
    target_domain = shop_domain or SHOPIFY_DOMAIN
    token         = access_token or SHOPIFY_ACCESS_TOKEN

    url     = f"https://{target_domain}/admin/api/2024-01/orders/{order_id}/transactions.json"
    headers = {"X-Shopify-Access-Token": token, "Content-Type": "application/json"}
    payload = {
        "transaction": {
            "kind": "capture",
            "status": "success",
            "amount": amount,
            "gateway": "interac-manual",
            "authorization": transaction_id
        }
    }

    try:
        response = requests.post(url, json=payload, headers=headers)
        if response.status_code == 201:
            print(f"🎉 SUCCESS! Order #{order_id} Paid on {target_domain}. Ref: {transaction_id}")
        else:
            print(f"❌ Shopify Update Failed: {response.text}")
    except Exception as e:
        print(f"❌ Connection Error: {e}")


def mark_shopify_order_failed(order_id, amount, reason, shop_domain=None, access_token=None):
    """Tags a failed order on the correct Shopify store."""
    target_domain = shop_domain or SHOPIFY_DOMAIN
    token         = access_token or SHOPIFY_ACCESS_TOKEN

    url     = f"https://{target_domain}/admin/api/2024-01/orders/{order_id}.json"
    headers = {"X-Shopify-Access-Token": token, "Content-Type": "application/json"}

    try:
        get_response  = requests.get(url, headers=headers)
        order_data    = get_response.json().get("order", {})
        current_tags  = order_data.get("tags", "")
    except Exception:
        current_tags  = ""

    new_tags = f"{current_tags}, Payment Failed, Interac Failed"
    payload  = {
        "order": {
            "id": order_id,
            "tags": new_tags,
            "note": f"⚠️ PAYMENT FAILED \nReason: {reason} \nAmount: {amount}",
        }
    }

    try:
        response = requests.put(url, json=payload, headers=headers)
        if response.status_code == 200:
            print(f"✅ Shopify Updated: Order #{order_id} tagged as FAILED on {target_domain}.")
            void_transaction(order_id, target_domain, token)
        else:
            print(f"❌ Shopify Update Failed: {response.text}")
    except Exception as e:
        print(f"❌ Connection Error: {e}")


def void_transaction(order_id, shop_domain=None, access_token=None):
    """Voids a pending transaction on the correct Shopify store."""
    target_domain = shop_domain or SHOPIFY_DOMAIN
    token         = access_token or SHOPIFY_ACCESS_TOKEN

    url     = f"https://{target_domain}/admin/api/2024-01/orders/{order_id}/transactions.json"
    headers = {"X-Shopify-Access-Token": token, "Content-Type": "application/json"}
    requests.post(url, json={"transaction": {"kind": "void"}}, headers=headers)


# ---------------------------------------------------------------------------
# DASHBOARD & ADMIN ROUTES
# ---------------------------------------------------------------------------

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        password = request.form.get("password")
        if password == ADMIN_PASSWORD:
            session["logged_in"] = True
            return redirect(url_for("dashboard"))
        return "<h3>Invalid Password!</h3><a href='/login'>Try again</a>"

    return """
    <div style="font-family:'Inter',sans-serif;max-width:400px;margin:100px auto;padding:40px;
                border-radius:12px;background:#1a1a1a;color:white;box-shadow:0 10px 30px rgba(0,0,0,0.5);">
        <h2 style="text-align:center;margin-bottom:30px;">FintechWerx Admin</h2>
        <form method="POST">
            <label style="display:block;margin-bottom:10px;color:#aaa;">Enter Admin Password:</label>
            <input type="password" name="password" required autofocus
                   style="width:100%;padding:12px;margin-bottom:20px;border-radius:6px;
                          border:1px solid #333;background:#2a2a2a;color:white;">
            <button type="submit"
                    style="width:100%;padding:12px;border:none;border-radius:6px;
                           background:#FFD100;color:black;font-weight:bold;cursor:pointer;">
                Login to Dashboard
            </button>
        </form>
    </div>
    """


@app.route("/logout")
def logout():
    session.pop("logged_in", None)
    return redirect(url_for("login"))


@app.route("/dashboard", methods=["GET"])
def dashboard():
    if not session.get("logged_in"):
        return redirect(url_for("login"))

    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM domains ORDER BY created_at DESC")
        domains = cursor.fetchall()
        cursor.close()
        conn.close()
    except Exception as e:
        return f"<h3>Database Connection Error</h3><p>{e}</p>"

    rows_html = ""
    for d in domains:
        status_color = "#28a745" if d["status"] == "active" else "#dc3545"
        token_display = (d.get("access_token") or "")[:20] + "…" if d.get("access_token") else "<i style='color:#888'>Not set</i>"
        rows_html += f"""
        <tr style="border-bottom:1px solid #333;">
            <td style="padding:15px;">{d['domain']}</td>
            <td style="padding:15px;">{token_display}</td>
            <td style="padding:15px;">
                <span style="background:{status_color};padding:4px 10px;border-radius:20px;font-size:12px;font-weight:bold;">
                    {d['status'].upper()}
                </span>
            </td>
            <td style="padding:15px;">{d['created_at']}</td>
            <td style="padding:15px;">
                <form action="/dashboard/set-token" method="POST" style="display:inline;">
                    <input type="hidden" name="id" value="{d['id']}">
                    <input type="text" name="token" placeholder="shpat_…" required
                           style="padding:4px 8px;border-radius:4px;border:1px solid #555;background:#333;color:white;width:180px;">
                    <button type="submit" style="background:#17a2b8;color:white;border:none;padding:5px 10px;border-radius:4px;cursor:pointer;">Set Token</button>
                </form>
                &nbsp;
                <form action="/dashboard/toggle" method="POST" style="display:inline;">
                    <input type="hidden" name="id" value="{d['id']}">
                    <button type="submit" style="background:#444;color:white;border:none;padding:5px 10px;border-radius:4px;cursor:pointer;">Toggle</button>
                </form>
                &nbsp;
                <form action="/dashboard/delete" method="POST" style="display:inline;">
                    <input type="hidden" name="id" value="{d['id']}">
                    <button type="submit" style="background:#dc3545;color:white;border:none;padding:5px 10px;border-radius:4px;cursor:pointer;"
                            onclick="return confirm('Delete this domain?')">Delete</button>
                </form>
            </td>
        </tr>
        """

    return f"""
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>FintechWerx Dashboard</title>
        <style>
            body {{ font-family:'Inter',sans-serif;background:#0f0f0f;color:#eee;margin:0;padding:40px; }}
            .container {{ max-width:1200px;margin:0 auto; }}
            .card {{ background:#1a1a1a;padding:30px;border-radius:12px;box-shadow:0 4px 20px rgba(0,0,0,0.5); }}
            h1 {{ margin-top:0;display:flex;justify-content:space-between;align-items:center; }}
            table {{ width:100%;border-collapse:collapse;margin-top:20px; }}
            th {{ text-align:left;padding:15px;background:#222; }}
            .add-form {{ margin-bottom:30px;background:#222;padding:20px;border-radius:8px; }}
            input[type=text], input[type=email] {{ padding:10px;border-radius:4px;border:1px solid #333;background:#333;color:white;width:280px; }}
            .btn-add {{ padding:10px 20px;background:#FFD100;border:none;border-radius:4px;font-weight:bold;cursor:pointer; }}
            .logout {{ font-size:14px;text-decoration:none;color:#aaa; }}
        </style>
    </head>
    <body>
        <div class="container">
            <h1>FintechWerx Domain Management <a href="/logout" class="logout">Logout</a></h1>
            <div class="card">
                <div class="add-form">
                    <form action="/dashboard/add" method="POST">
                        <input type="text" name="domain" placeholder="example-store.myshopify.com" required>
                        &nbsp;
                        <input type="text" name="token" placeholder="shpat_… (Shopify Access Token)" required>
                        &nbsp;
                        <button type="submit" class="btn-add">Add Store</button>
                    </form>
                </div>
                <table>
                    <thead>
                        <tr>
                            <th>Store Domain</th>
                            <th>Access Token</th>
                            <th>Status</th>
                            <th>Added On</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>{rows_html}</tbody>
                </table>
            </div>
        </div>
    </body>
    </html>
    """


@app.route("/dashboard/add", methods=["POST"])
def dashboard_add():
    if not session.get("logged_in"):
        return redirect(url_for("login"))
    domain = request.form.get("domain", "").strip()
    token  = request.form.get("token", "").strip()
    if domain:
        try:
            conn = get_db_connection()
            cursor = conn.cursor()
            cursor.execute(
                "INSERT INTO domains (domain, access_token, status) VALUES (%s, %s, 'active')"
                " ON DUPLICATE KEY UPDATE access_token = VALUES(access_token)",
                (domain, token or None)
            )
            conn.commit()
            cursor.close()
            conn.close()
        except Exception as e:
            print(f"dashboard_add error: {e}")
    return redirect(url_for("dashboard"))


@app.route("/dashboard/set-token", methods=["POST"])
def dashboard_set_token():
    if not session.get("logged_in"):
        return redirect(url_for("login"))
    domain_id = request.form.get("id")
    token     = request.form.get("token", "").strip()
    try:
        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute(
            "UPDATE domains SET access_token = %s WHERE id = %s",
            (token or None, domain_id)
        )
        conn.commit()
        cursor.close()
        conn.close()
    except Exception as e:
        print(f"dashboard_set_token error: {e}")
    return redirect(url_for("dashboard"))


@app.route("/dashboard/toggle", methods=["POST"])
def dashboard_toggle():
    if not session.get("logged_in"):
        return redirect(url_for("login"))
    domain_id = request.form.get("id")
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT status FROM domains WHERE id = %s", (domain_id,))
        row = cursor.fetchone()
        new_status = "inactive" if row["status"] == "active" else "active"
        cursor.execute("UPDATE domains SET status = %s WHERE id = %s", (new_status, domain_id))
        conn.commit()
        cursor.close()
        conn.close()
    except Exception as e:
        print(f"dashboard_toggle error: {e}")
    return redirect(url_for("dashboard"))


@app.route("/dashboard/delete", methods=["POST"])
def dashboard_delete():
    if not session.get("logged_in"):
        return redirect(url_for("login"))
    domain_id = request.form.get("id")
    try:
        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("DELETE FROM domains WHERE id = %s", (domain_id,))
        conn.commit()
        cursor.close()
        conn.close()
    except Exception as e:
        print(f"dashboard_delete error: {e}")
    return redirect(url_for("dashboard"))


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8080)