<!-- QRScannerDialog.vue -->
<template>
  <div
    v-if="visible && !isNativePlatform"
    class="dialog-overlay z-[60] fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"
  >
    <div
      class="dialog relative bg-white rounded-lg shadow-xl max-w-lg w-full mx-4"
    >
      <!-- Header -->
      <div
        class="p-4 border-b border-gray-200 flex justify-between items-center"
      >
        <div>
          <h3 class="text-lg font-medium text-gray-900">Scan QR Code</h3>
          <span class="text-xs text-gray-500">v1.1.0 build 00000</span>
        </div>
        <button
          class="text-gray-400 hover:text-gray-500"
          aria-label="Close dialog"
          @click="close"
        >
          <svg
            class="h-6 w-6"
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              stroke-width="2"
              d="M6 18L18 6M6 6l12 12"
            />
          </svg>
        </button>
      </div>

      <!-- Scanner -->
      <div class="p-4">
        <div
          v-if="useQRReader && !isNativePlatform"
          class="relative aspect-square"
        >
          <!-- Status Message -->
          <div
            class="absolute top-0 left-0 right-0 bg-black bg-opacity-50 text-white text-center py-2 z-10"
          >
            <div
              v-if="isInitializing"
              class="flex items-center justify-center space-x-2"
            >
              <svg
                class="animate-spin h-5 w-5 text-white"
                xmlns="http://www.w3.org/2000/svg"
                fill="none"
                viewBox="0 0 24 24"
              >
                <circle
                  class="opacity-25"
                  cx="12"
                  cy="12"
                  r="10"
                  stroke="currentColor"
                  stroke-width="4"
                ></circle>
                <path
                  class="opacity-75"
                  fill="currentColor"
                  d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 
    3.042 1.135 5.824 3 7.938l3-2.647z"
                ></path>
              </svg>
              <span>{{ initializationStatus }}</span>
            </div>
            <p
              v-else-if="isScanning"
              class="flex items-center justify-center space-x-2"
            >
              <span
                class="inline-block w-2 h-2 bg-green-500 rounded-full animate-pulse"
              ></span>
              <span>Position QR code in the frame</span>
            </p>
            <p v-else-if="error" class="text-red-300">
              <span class="font-medium">Error:</span> {{ error }}
            </p>
            <p v-else class="flex items-center justify-center space-x-2">
              <span
                class="inline-block w-2 h-2 bg-blue-500 rounded-full"
              ></span>
              <span>Ready to scan</span>
            </p>
          </div>

          <qrcode-stream
            :camera="preferredCamera"
            @decode="onDecode"
            @init="onInit"
            @detect="onDetect"
            @error="onError"
            @camera-on="onCameraOn"
            @camera-off="onCameraOff"
          />

          <!-- Scanning Frame -->
          <div
            class="absolute inset-0 border-2"
            :class="{
              'border-blue-500': !error && !isScanning,
              'border-green-500 animate-pulse': isScanning,
              'border-red-500': error,
            }"
            style="opacity: 0.5; pointer-events: none"
          ></div>

          <!-- Debug Info -->
          <div
            class="absolute bottom-16 left-0 right-0 bg-black bg-opacity-50 text-white text-xs text-center py-1"
          >
            Camera: {{ preferredCamera === "user" ? "Front" : "Back" }} |
            Status: {{ cameraStatus }}
          </div>

          <!-- Camera Switch Button -->
          <button
            class="absolute bottom-4 right-4 bg-white rounded-full p-2 shadow-lg"
            title="Switch camera"
            @click="toggleCamera"
          >
            <svg
              class="h-6 w-6 text-gray-600"
              fill="none"
              viewBox="0 0 24 24"
              stroke="currentColor"
            >
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 
        011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"
              />
              <path
                stroke-linecap="round"
                stroke-linejoin="round"
                stroke-width="2"
                d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"
              />
            </svg>
          </button>
        </div>
        <div v-else class="text-center py-8">
          <p class="text-gray-500">
            {{
              isNativePlatform
                ? "Using native camera scanner..."
                : "QR code scanning is not supported in this browser."
            }}
          </p>
          <p v-if="!isNativePlatform" class="text-sm text-gray-400 mt-2">
            Please ensure you're using a modern browser with camera access.
          </p>
        </div>
      </div>

      <!-- Footer -->
      <div class="p-4 border-t border-gray-200">
        <div class="flex flex-col space-y-4">
          <!-- Instructions -->
          <div class="text-sm text-gray-600">
            <ul class="list-disc list-inside space-y-1">
              <li>Ensure the QR code is well-lit and in focus</li>
              <li>Hold your device steady</li>
              <li>The QR code should fit within the scanning frame</li>
            </ul>
          </div>

          <!-- Error Message -->
          <p v-if="error" class="text-red-500 text-sm">{{ error }}</p>

          <!-- Actions -->
          <div class="flex justify-end space-x-2">
            <button
              v-if="error"
              class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
              @click="retryScanning"
            >
              Retry
            </button>
            <button
              class="px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200"
              @click="close"
            >
              Cancel
            </button>
          </div>
        </div>
      </div>

      <div v-if="debugMessage" class="bg-yellow-200 text-black p-2 m-2 rounded">
        {{ debugMessage }}
      </div>

      <div class="bg-red-200 text-black p-2 m-2 rounded">
        DEBUG PANEL: If you see this, the template is updating.
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator";
import { QrcodeStream } from "vue-qrcode-reader";
import { QRScannerOptions } from "@/services/QRScanner/types";
import { logger } from "@/utils/logger";
import { Capacitor } from "@capacitor/core";

interface ScanProps {
  onScan: (result: string) => void;
  onError?: (error: Error) => void;
  options?: QRScannerOptions;
}

interface DetectionResult {
  content?: string;
  location?: {
    topLeft: { x: number; y: number };
    topRight: { x: number; y: number };
    bottomLeft: { x: number; y: number };
    bottomRight: { x: number; y: number };
  };
}

@Component({
  components: {
    QrcodeStream,
  },
})
export default class QRScannerDialog extends Vue {
  @Prop({ type: Function, required: true }) onScan!: ScanProps["onScan"];
  @Prop({ type: Function }) onError?: ScanProps["onError"];
  @Prop({ type: Object }) options?: ScanProps["options"];

  // Version
  readonly version = "1.1.0";

  visible = true;
  error: string | null = null;
  useQRReader = __USE_QR_READER__;
  isNativePlatform =
    Capacitor.isNativePlatform() ||
    __IS_MOBILE__ ||
    Capacitor.getPlatform() === "android" ||
    Capacitor.getPlatform() === "ios";

  isInitializing = true;
  isScanning = false;
  preferredCamera: "user" | "environment" = "environment";
  initializationStatus = "Checking camera access...";
  cameraStatus = "Initializing";
  debugMessage = "";

  created() {
    logger.log("QRScannerDialog platform detection:", {
      capacitorNative: Capacitor.isNativePlatform(),
      isMobile: __IS_MOBILE__,
      platform: Capacitor.getPlatform(),
      useQRReader: this.useQRReader,
      isNativePlatform: this.isNativePlatform,
      userAgent: navigator.userAgent,
      mediaDevices: !!navigator.mediaDevices,
      getUserMedia: !!(
        navigator.mediaDevices && navigator.mediaDevices.getUserMedia
      ),
    });

    // If on native platform, close immediately and don't initialize web scanner
    if (this.isNativePlatform) {
      logger.log("Closing QR dialog on native platform");
      this.$nextTick(() => this.close());
    }
  }

  async onInit(promise: Promise<void>) {
    alert("onInit called");
    this.debugMessage = "onInit called";
    let timeoutHit = false;
    const timeout = setTimeout(() => {
      timeoutHit = true;
      this.isInitializing = false;
      this.cameraStatus = "Ready (timeout fallback)";
      this.initializationStatus = "Camera ready (fallback)";
      alert("Timeout fallback triggered");
      this.debugMessage = "Timeout fallback triggered";
    }, 4000);

    try {
      await promise;
      if (!timeoutHit) {
        clearTimeout(timeout);
        this.isInitializing = false;
        this.cameraStatus = "Ready";
        alert("Promise resolved before timeout");
        this.debugMessage = "Promise resolved before timeout";
      }
    } catch (error) {
      clearTimeout(timeout);
      alert("Promise rejected: " + (error instanceof Error ? error.message : error));
      this.debugMessage = "Promise rejected: " + (error instanceof Error ? error.message : error);
      if (error instanceof Error) {
        this.error = error.message;
        this.cameraStatus = "Error";
        if (this.onError) {
          this.onError(error);
        }
        logger.error("Error initializing QR scanner:", {
          error: error.message,
          stack: error.stack,
          name: error.name,
          type: error.constructor.name,
        });
      }
    } finally {
      this.isInitializing = false;
    }
  }

  onCameraOn(): void {
    this.cameraStatus = "Active";
    logger.log("Camera turned on successfully");
  }

  onCameraOff(): void {
    this.cameraStatus = "Off";
    logger.log("Camera turned off");
  }

  onDetect(result: DetectionResult | Promise<DetectionResult>): void {
    this.isScanning = true;
    this.cameraStatus = "Detecting";
    logger.log("QR code detected, processing...");

    // Handle both promise and direct value cases
    const processResult = (detection: DetectionResult) => {
      try {
        logger.log("QR code processed successfully:", detection);
      } catch (error) {
        this.handleError(error);
      } finally {
        this.isScanning = false;
        this.cameraStatus = "Active";
      }
    };

    // Handle both promise and non-promise results
    if (result && typeof result.then === "function") {
      result
        .then(processResult)
        .catch((error: Error) => this.handleError(error))
        .finally(() => {
          this.isScanning = false;
          this.cameraStatus = "Active";
        });
    } else {
      processResult(result);
    }
  }

  private handleError(error: unknown): void {
    const wrappedError =
      error instanceof Error ? error : new Error(String(error));
    this.error = wrappedError.message;
    this.cameraStatus = "Error";

    if (this.onError) {
      this.onError(wrappedError);
    }

    logger.error("QR scanner error:", {
      error: wrappedError.message,
      stack: wrappedError.stack,
      name: wrappedError.name,
      type: wrappedError.constructor.name,
    });
  }

  onDecode(result: string): void {
    logger.log("QR code decoded:", result);
    try {
      this.onScan(result);
      this.close();
    } catch (error) {
      this.handleError(error);
    }
  }

  toggleCamera(): void {
    this.preferredCamera =
      this.preferredCamera === "user" ? "environment" : "user";
  }

  retryScanning(): void {
    this.error = null;
    this.isInitializing = true;
    // The QR scanner component will automatically reinitialize
  }

  async close(): Promise<void> {
    logger.log("Closing QR scanner dialog");
    this.visible = false;
    await this.$nextTick();
    if (this.$el && this.$el.parentNode) {
      this.$el.parentNode.removeChild(this.$el);
    }
  }
}
</script>

<style scoped>
.dialog-overlay {
  backdrop-filter: blur(4px);
}

.qrcode-stream {
  width: 100%;
  height: 100%;
}

@keyframes pulse {
  0% {
    opacity: 0.5;
  }
  50% {
    opacity: 0.75;
  }
  100% {
    opacity: 0.5;
  }
}

.animate-pulse {
  animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
</style>
