import { FieldType, type Segment } from "@hamradio/packet";

import { DO_NOT_ARCHIVE_MARKER, DataType, type Payload, type StatusPayload } from "./frame.types";
import Timestamp from "./timestamp";

export const decodeStatusPayload = (
  raw: string,
  withStructure: boolean = false
): {
  payload: Payload | null;
  segment?: Segment[];
} => {
  // Status payload: optional 7-char timestamp followed by free text.
  // We'll also detect a trailing Maidenhead locator (4 or 6 chars) and expose it.
  const offsetBase = 1; // skip data type identifier '>'
  if (raw.length <= offsetBase) return { payload: null };

  let offset = offsetBase;
  const segments: Segment[] = withStructure ? [] : [];

  // Try parse optional timestamp (7 chars)
  if (raw.length >= offset + 7) {
    const timeStr = raw.substring(offset, offset + 7);
    const { timestamp, segment: tsSegment } = Timestamp.fromString(timeStr, withStructure);
    if (timestamp) {
      offset += 7;
      if (tsSegment) segments.push(tsSegment);
    }
  }

  // Remaining text is status text
  const text = raw.substring(offset);
  if (!text) return { payload: null };
  const doNotArchive = text.includes(DO_NOT_ARCHIVE_MARKER);

  // Detect trailing Maidenhead locator (4 or 6 chars) at end of text separated by space
  let maidenhead: string | undefined;
  const mhMatch = text.match(/\s([A-Ra-r]{2}\d{2}(?:[A-Ra-r]{2})?)$/);
  let statusText = text;
  if (mhMatch) {
    maidenhead = mhMatch[1].toUpperCase();
    statusText = text.slice(0, mhMatch.index).trimEnd();
  }

  const payload: StatusPayload = {
    type: DataType.Status,
    doNotArchive,
    timestamp: undefined,
    text: statusText
  };

  // If timestamp was parsed, attach it
  if (segments.length > 0) {
    // The first segment may be timestamp; parseTimestamp returns the Timestamp object
    // Re-parse to obtain timestamp object (cheap) - alternate would be to capture earlier
    const timeSegment = segments.find((s) => s.name === "timestamp");
    if (timeSegment) {
      const tsStr = new TextDecoder().decode(timeSegment.data);
      const { timestamp } = Timestamp.fromString(tsStr, false);
      if (timestamp) payload.timestamp = timestamp;
    }
  }

  if (maidenhead) payload.maidenhead = maidenhead;

  if (withStructure) {
    segments.push({
      name: "status",
      data: new TextEncoder().encode(text).buffer,
      isString: true,
      fields: [{ type: FieldType.STRING, name: "text", length: text.length }]
    });
    return { payload, segment: segments };
  }

  return { payload };
};

export default decodeStatusPayload;
