import React from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { useSettings, useTranslation, useDateTime } from '@tamanu/ui-components';
import { getDrugUnitLabel } from '@tamanu/shared/utils/medication';
import { Colors } from '../../../constants';
import { TranslatedText } from '../../Translation';

const Label = styled.div`
  width: ${props => props.$width}mm;
  height: ${props => props.$height}mm;
  font-size: ${props => props.$fontSize}mm;
  line-height: ${props => props.$fontSize}mm;
  border: 0.354mm solid ${Colors.black};
  border-radius: 1.062mm;
  position: relative;
  overflow: hidden;
  background-color: ${Colors.white};
  page-break-inside: avoid;
  break-inside: avoid;
  display: flex;
  flex-direction: column;

  @media print {
    width: ${props => props.$width}mm;
    height: ${props => props.$height}mm;
  }
`;

const LabelContent = styled.div`
  padding: 0.7mm 2mm 0 2mm;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  flex-grow: 1;
`;

const LabelTopSection = styled.div`
  display: flex;
  flex-direction: column;
  gap: 0.4mm;
  margin-bottom: 1mm;
`;

const LabelMedicationName = styled.div`
  font-weight: 500;
  font-size: ${props => props.$fontSize}mm;
  line-height: ${props => props.$fontSize * 1.2}mm;
  word-wrap: break-word;
  overflow-wrap: break-word;
`;

const LabelInstructions = styled.div`
  font-weight: 400;
  font-size: ${props => props.$fontSize}mm;
  line-height: ${props => props.$fontSize * 1.2}mm;
  word-wrap: break-word;
  overflow-wrap: break-word;
`;

const LabelBottomSection = styled.div`
  display: flex;
  justify-content: space-between;
  gap: 2mm;
  margin-top: 0.354mm;
`;

const LabelPatientDateRow = styled.div`
  display: flex;
  gap: 2mm;
  margin-top: auto;
  border-bottom: 0.354mm solid ${Colors.black};
  padding-bottom: 0.354mm;
`;

const LabelPatientName = styled.div`
  font-weight: 700;
  font-size: ${props => props.$fontSize}mm;
  line-height: ${props => props.$fontSize * 1.125}mm;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
`;

const LabelDate = styled.div`
  font-weight: 400;
  font-size: ${props => props.$fontSize}mm;
  line-height: ${props => props.$fontSize * 1.125}mm;
  text-align: right;
  white-space: nowrap;
  flex-shrink: 0;
`;

const LabelLeftColumn = styled.div`
  display: flex;
  flex-direction: column;
  gap: 0.4mm;
  flex: 1;
  min-width: 0;
`;

const LabelRightColumn = styled.div`
  display: flex;
  flex-direction: column;
  gap: 0.4mm;
  flex: 1;
  min-width: 0;
`;

const LabelDetailRow = styled.div`
  font-weight: 400;
  font-size: ${props => props.$fontSize}mm;
  line-height: ${props => props.$fontSize * 1.125}mm;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
`;

const LabelFooter = styled.div`
  border-top: 0.177mm solid ${Colors.black};
  padding: 0.4mm 0 0.2mm;
  margin-top: 0.354mm;
  display: flex;
  justify-content: center;
  align-items: center;
`;

const LabelFooterText = styled.div`
  font-weight: 400;
  text-align: center;
  font-size: ${props => props.$fontSize}mm;
  line-height: ${props => props.$fontSize * 1.125}mm;
  word-wrap: break-word;
  overflow-wrap: break-word;
`;

export const useLabelDimensions = () => {
  const { getSetting } = useSettings();
  const width = getSetting('medications.dispensing.prescriptionLabelSize.width') ?? 80;
  const height = getSetting('medications.dispensing.prescriptionLabelSize.height') ?? 40;
  return { width, height };
};

export const getMedicationLabel = (quantity, units, getEnumTranslation) => {
  if (!quantity) return '';
  if (!units) return `${quantity}`;
  return `${quantity} ${getDrugUnitLabel(units, quantity, getEnumTranslation).toLowerCase()}`;
};

const calculateDynamicFontSizes = (data, labelWidth, labelHeight) => {
  const medicationNameLength = data.medicationName?.length || 0;
  const instructionsLength = data.instructions?.length || 0;

  // 1. Medication name: scale based on length
  let medicationNameFontSize = labelHeight * 0.09;
  if (medicationNameLength > 50) {
    medicationNameFontSize = labelHeight * 0.075;
  } else if (medicationNameLength > 35) {
    medicationNameFontSize = labelHeight * 0.08;
  } else if (medicationNameLength < 25) {
    medicationNameFontSize = labelHeight * 0.11;
  }

  // 2. Instructions / Label text: scale down for longer text so the footer
  // and other fixed sections still fit. Uppercase preset-label text is wider
  // per char than mixed-case English, so the thresholds step harder than the
  // medication-name ladder above. Thresholds are tuned for the default 80x40
  // shape; capacity is bound by chars-per-line, which is `width / fontSize`
  // and the font scales with `labelHeight`, so a tall-thin label fits LESS
  // text per row than the default.
  const widthHeightScale = (labelWidth * 40) / (labelHeight * 80);
  let instructionsFontSize = labelHeight * 0.145;
  if (instructionsLength > 150 * widthHeightScale) {
    instructionsFontSize = labelHeight * 0.09;
  } else if (instructionsLength > 110 * widthHeightScale) {
    instructionsFontSize = labelHeight * 0.11;
  } else if (instructionsLength > 50 * widthHeightScale) {
    instructionsFontSize = labelHeight * 0.125;
  }

  // When the medication name is long enough to shrink AND wrap to two lines it
  // costs an extra line, so step long instructions down (kept as large as fits)
  // to drop a line and keep the footer on a fixed-size label.
  if (medicationNameLength > 45 && instructionsLength > 75 * widthHeightScale) {
    instructionsFontSize = Math.min(instructionsFontSize, labelHeight * 0.095);
  }


  // 3 & 4. Patient name/date and the detail rows (Pres, Request, quantity,
  // Repeats) are secondary info — sized to match the footer to free vertical
  // space for the medication name and instructions. Long values truncate.
  const footerFontSize = labelHeight * 0.075; // Fixed 3mm for 40mm height
  const patientDateFontSize = footerFontSize;
  const detailFontSize = footerFontSize;
  
  return {
    medicationNameFontSize,
    instructionsFontSize,
    patientDateFontSize,
    detailFontSize,
    footerFontSize,
  };
};

export const MedicationLabel = React.memo(({ data }) => {
  const { formatShortest } = useDateTime();
  const { getEnumTranslation } = useTranslation();
  const { getSetting } = useSettings();
  const labelWidth = getSetting('medications.dispensing.prescriptionLabelSize.width') ?? 80;
  const labelHeight = getSetting('medications.dispensing.prescriptionLabelSize.height') ?? 40;

  const {
    medicationName,
    instructions,
    patientName,
    dispensedAt,
    quantity,
    units,
    remainingRepeats,
    prescriberName,
    requestNumber,
    facilityName,
  } = data;

  const {
    medicationNameFontSize,
    instructionsFontSize,
    patientDateFontSize,
    detailFontSize,
    footerFontSize,
  } = calculateDynamicFontSizes(data, labelWidth, labelHeight);

  return (
    <Label $width={labelWidth} $height={labelHeight} $fontSize={instructionsFontSize}>
      <LabelContent>
        <LabelTopSection>
          <LabelMedicationName $fontSize={medicationNameFontSize}>
            {medicationName}
          </LabelMedicationName>
          <LabelInstructions $fontSize={instructionsFontSize}>
            {instructions}
          </LabelInstructions>
        </LabelTopSection>
        <LabelPatientDateRow>
          <LabelPatientName $fontSize={patientDateFontSize}>{patientName}</LabelPatientName>
          <LabelDate $fontSize={patientDateFontSize}>{formatShortest(dispensedAt)}</LabelDate>
        </LabelPatientDateRow>
        <LabelBottomSection>
          <LabelLeftColumn>
            <LabelDetailRow $fontSize={detailFontSize}>{getMedicationLabel(quantity, units, getEnumTranslation)}</LabelDetailRow>
            <LabelDetailRow $fontSize={detailFontSize}>
              <TranslatedText
                stringId="medication.dispense.repeats"
                fallback="Repeats"
              />
              : {remainingRepeats}
            </LabelDetailRow>
          </LabelLeftColumn>
          <LabelRightColumn>
            <LabelDetailRow $fontSize={detailFontSize}>
              <TranslatedText stringId="medication.prescriber.label" fallback="Prescriber" />:{' '}
              {prescriberName}
            </LabelDetailRow>
            <LabelDetailRow $fontSize={detailFontSize}>
              <TranslatedText stringId="medication.dispense.request" fallback="Request" />:{' '}
              {requestNumber}
            </LabelDetailRow>
          </LabelRightColumn>
        </LabelBottomSection>
      </LabelContent>
      <LabelFooter>
        <LabelFooterText $fontSize={footerFontSize}>{facilityName}</LabelFooterText>
      </LabelFooter>
    </Label>
  );
});

export const medicationLabelShape = PropTypes.shape({
  id: PropTypes.string,
  medicationName: PropTypes.string.isRequired,
  instructions: PropTypes.string.isRequired,
  patientName: PropTypes.string.isRequired,
  dispensedAt: PropTypes.string.isRequired,
  quantity: PropTypes.number.isRequired,
  units: PropTypes.string,
  remainingRepeats: PropTypes.number.isRequired,
  prescriberName: PropTypes.string.isRequired,
  requestNumber: PropTypes.string.isRequired,
  facilityName: PropTypes.string,
});

MedicationLabel.propTypes = {
  data: medicationLabelShape.isRequired,
};
