/** * GiftDetailsStep.vue - Gift details step component * * Extracted from
GiftedDialog.vue to handle the complete step 2 * gift details form interface
with entity summaries and validation. * * Features: * - Entity summary display
with edit capability * - Gift description input with placeholder support * -
Amount input with increment/decrement controls * - Unit code selection (HUR,
USD, BTC, etc.) * - Photo & more options navigation * - Conflict detection and
warning display * - Form validation and submission * - Cancel functionality * -
Template streamlined with computed CSS properties * - Function props for parent
control over updates and validation * * @author Matthew Raymer */
<template>
  <div id="sectionGiftedGift">
    <!-- Entity Summary Buttons -->
    <div class="grid grid-cols-2 gap-2 mb-4">
      <!-- Giver Button -->
      <EntitySummaryButton
        :entity="giver"
        :entity-type="giverEntityType"
        :label="giverLabel"
        :editable="canEditGiver"
        :on-edit-requested="handleEditGiver"
      />

      <!-- Recipient Button -->
      <EntitySummaryButton
        :entity="receiver"
        :entity-type="recipientEntityType"
        :label="recipientLabel"
        :editable="canEditRecipient"
        :on-edit-requested="handleEditRecipient"
      />
    </div>

    <!-- Gift Description Input -->
    <input
      v-model="localDescription"
      type="text"
      class="block w-full rounded border border-slate-400 px-3 py-2 mb-4 placeholder:italic"
      :placeholder="prompt || 'What was given?'"
      @input="handleDescriptionChange"
    />

    <!-- Amount Input and Unit Selection -->
    <div class="flex mb-4">
      <AmountInput
        :value="localAmount"
        :min="0"
        input-id="inputGivenAmount"
        :on-update-value="handleAmountChange"
      />

      <select
        v-model="localUnitCode"
        class="flex-1 rounded border border-slate-400 ms-2 px-3 py-2"
        @change="handleUnitCodeChange"
      >
        <option value="HUR">Hours</option>
        <option value="USD">US $</option>
        <option value="BTC">BTC</option>
        <option value="BX">BX</option>
        <option value="ETH">ETH</option>
      </select>
    </div>

    <!-- Photo & More Options Link -->
    <router-link :to="photoOptionsRoute" :class="photoOptionsClasses">
      Photo &amp; more options&hellip;
    </router-link>

    <!-- Sign & Send Info -->
    <p class="text-center text-sm mb-4">
      <b class="font-medium">Sign &amp; Send</b> to publish to the world
      <font-awesome
        icon="circle-info"
        class="fa-fw text-blue-500 text-base cursor-pointer"
        @click="handleExplainData"
      />
    </p>

    <!-- Conflict Warning -->
    <div
      v-if="hasConflict"
      class="mb-4 p-3 bg-red-50 border border-red-200 rounded-md"
    >
      <p class="text-red-700 text-sm text-center">
        <font-awesome icon="exclamation-triangle" class="fa-fw mr-1" />
        Cannot record: Same person selected as both giver and recipient
      </p>
    </div>

    <!-- Action Buttons -->
    <div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
      <button
        :disabled="hasConflict"
        :class="submitButtonClasses"
        @click="handleSubmit"
      >
        Sign &amp; Send
      </button>
      <button :class="cancelButtonClasses" @click="handleCancel">Cancel</button>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch, Emit } from "vue-facing-decorator";
import EntitySummaryButton from "./EntitySummaryButton.vue";
import AmountInput from "./AmountInput.vue";
import { RouteLocationRaw } from "vue-router";
import { logger } from "@/utils/logger";

/**
 * Entity data interface for giver/receiver
 */
interface EntityData {
  did?: string;
  handleId?: string;
  name?: string;
  image?: string;
}

/**
 * GiftDetailsStep - Complete step 2 gift details form interface
 *
 * Features:
 * - Entity summary display with edit capability
 * - Gift description input with placeholder support
 * - Amount input with increment/decrement controls
 * - Unit code selection (HUR, USD, BTC, etc.)
 * - Photo & more options navigation
 * - Conflict detection and warning display
 * - Form validation and submission
 * - Cancel functionality
 * - Template streamlined with computed CSS properties
 * - Function props for parent control over updates and validation
 */
@Component({
  components: {
    EntitySummaryButton,
    AmountInput,
  },
})
export default class GiftDetailsStep extends Vue {
  /** Giver entity data */
  @Prop({ required: true })
  giver!: EntityData | null;

  /** Receiver entity data */
  @Prop({ required: true })
  receiver!: EntityData | null;

  /** Type of giver entity: 'person' or 'project' */
  @Prop({ required: true })
  giverEntityType!: "person" | "project";

  /** Type of recipient entity: 'person' or 'project' */
  @Prop({ required: true })
  recipientEntityType!: "person" | "project";

  /** Gift description */
  @Prop({ default: "" })
  description!: string;

  /** Gift amount */
  @Prop({ default: 0 })
  amount!: number;

  /** Unit code (HUR, USD, etc.) */
  @Prop({ default: "HUR" })
  unitCode!: string;

  /** Input placeholder text */
  @Prop({ default: "" })
  prompt!: string;

  /** Whether this is from a project view */
  @Prop({ default: false })
  isFromProjectView!: boolean;

  /** Whether there's a conflict between giver and receiver */
  @Prop({ default: false })
  hasConflict!: boolean;

  /** Offer ID for context */
  @Prop({ default: "" })
  offerId!: string;

  /** Project ID for context (giver) */
  @Prop({ default: "" })
  fromProjectId!: string;

  /** Project ID for context (recipient) */
  @Prop({ default: "" })
  toProjectId!: string;

  /**
   * Function prop for handling description updates
   * Called when the description input changes, allowing parent to control validation
   */
  @Prop({ type: Function, default: () => {} })
  onUpdateDescription!: (description: string) => void | Promise<void>;

  /**
   * Function prop for handling amount updates
   * Called when the amount changes, allowing parent to control validation
   */
  @Prop({ type: Function, default: () => {} })
  onUpdateAmount!: (amount: number) => void | Promise<void>;

  /**
   * Function prop for handling unit code updates
   * Called when the unit code selection changes, allowing parent to control validation
   */
  @Prop({ type: Function, default: () => {} })
  onUpdateUnitCode!: (unitCode: string) => void | Promise<void>;

  /** Local reactive copies of props for v-model */
  private localDescription: string = "";
  private localAmount: number = 0;
  private localUnitCode: string = "HUR";

  /**
   * CSS classes for the photo & more options link
   */
  get photoOptionsClasses(): string {
    return "block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg mb-4";
  }

  /**
   * CSS classes for the cancel button
   */
  get cancelButtonClasses(): string {
    return "block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg";
  }

  /**
   * Initialize local values from props
   */
  mounted(): void {
    this.localDescription = this.description;
    this.localAmount = this.amount;
    this.localUnitCode = this.unitCode;
  }

  /**
   * Watch for external prop changes
   */
  @Watch("description")
  onDescriptionChange(newValue: string): void {
    this.localDescription = newValue;
  }

  @Watch("amount")
  onAmountChange(newValue: number): void {
    this.localAmount = newValue;
  }

  @Watch("unitCode")
  onUnitCodeChange(newValue: string): void {
    this.localUnitCode = newValue;
  }

  /**
   * Computed label for giver entity
   */
  get giverLabel(): string {
    return this.giverEntityType === "project"
      ? "Benefited from:"
      : "Received from:";
  }

  /**
   * Computed label for recipient entity
   */
  get recipientLabel(): string {
    return this.recipientEntityType === "project"
      ? "Given to project:"
      : "Given to:";
  }

  /**
   * Whether the giver can be edited
   */
  get canEditGiver(): boolean {
    return !(this.isFromProjectView && this.giverEntityType === "project");
  }

  /**
   * Whether the recipient can be edited
   */
  get canEditRecipient(): boolean {
    return this.recipientEntityType === "person";
  }

  /**
   * Computed CSS classes for submit button
   */
  get submitButtonClasses(): string {
    if (this.hasConflict) {
      return "block w-full text-center text-md uppercase font-bold bg-gradient-to-b from-slate-300 to-slate-500 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-slate-400 px-1.5 py-2 rounded-lg cursor-not-allowed";
    }
    return "block w-full text-center text-md uppercase font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-lg";
  }

  /**
   * Computed route for photo & more options
   */
  get photoOptionsRoute(): RouteLocationRaw {
    return {
      name: "gifted-details",
      query: {
        amountInput: this.localAmount.toString(),
        description: this.localDescription,
        giverDid:
          this.giverEntityType === "person" ? this.giver?.did : undefined,
        giverName: this.giver?.name,
        offerId: this.offerId,
        fulfillsProjectId:
          this.recipientEntityType === "project" ? this.toProjectId : undefined,
        providerProjectId:
          this.giverEntityType === "project"
            ? this.giver?.handleId
            : this.fromProjectId,
        recipientDid:
          this.recipientEntityType === "person"
            ? this.receiver?.did
            : undefined,
        recipientName: this.receiver?.name,
        unitCode: this.localUnitCode,
      },
    };
  }

  /**
   * Handle description input changes
   * Calls the onUpdateDescription function prop for parent control
   */
  handleDescriptionChange(): void {
    this.onUpdateDescription(this.localDescription);
  }

  /**
   * Handle amount input changes
   * Calls the onUpdateAmount function prop for parent control
   */
  handleAmountChange(newAmount: number): void {
    logger.debug("[GiftDetailsStep] handleAmountChange() called", {
      oldAmount: this.localAmount,
      newAmount,
    });
    this.localAmount = newAmount;
    this.onUpdateAmount(newAmount);
  }

  /**
   * Handle unit code selection changes
   * Calls the onUpdateUnitCode function prop for parent control
   */
  handleUnitCodeChange(): void {
    this.onUpdateUnitCode(this.localUnitCode);
  }

  /**
   * Handle giver edit request
   * Called by EntitySummaryButton function prop
   */
  handleEditGiver(_data: {
    entityType: string;
    entity: EntityData | null;
  }): void {
    this.emitEditEntity({
      entityType: "giver",
      currentEntity: this.giver,
    });
  }

  /**
   * Handle recipient edit request
   * Called by EntitySummaryButton function prop
   */
  handleEditRecipient(_data: {
    entityType: string;
    entity: EntityData | null;
  }): void {
    this.emitEditEntity({
      entityType: "recipient",
      currentEntity: this.receiver,
    });
  }

  /**
   * Handle explain data info click
   */
  handleExplainData(): void {
    this.emitExplainData();
  }

  /**
   * Handle form submission
   */
  handleSubmit(): void {
    if (!this.hasConflict) {
      this.emitSubmit({
        description: this.localDescription,
        amount: this.localAmount,
        unitCode: this.localUnitCode,
      });
    }
  }

  /**
   * Handle cancel button click
   */
  handleCancel(): void {
    this.emitCancel();
  }

  // Emit methods using @Emit decorator (keeping these for non-update events)

  @Emit("edit-entity")
  emitEditEntity(data: {
    entityType: string;
    currentEntity: EntityData | null;
  }): { entityType: string; currentEntity: EntityData | null } {
    return data;
  }

  @Emit("explain-data")
  emitExplainData(): void {
    // No return value needed
  }

  @Emit("submit")
  emitSubmit(data: { description: string; amount: number; unitCode: string }): {
    description: string;
    amount: number;
    unitCode: string;
  } {
    return data;
  }

  @Emit("cancel")
  emitCancel(): void {
    // No return value needed
  }
}
</script>

<style scoped>
/* Component-specific styles if needed */
</style>
